private/Initialize-DeployOSDCloud.ps1
|
function Initialize-DeployOSDCloud { [CmdletBinding()] param ( [Parameter(Mandatory = $false, Position = 0, ValueFromPipelineByPropertyName = $true)] [Alias('Name')] [System.String] $WorkflowName = 'default', [Parameter(Mandatory = $false, HelpMessage = 'Optional local disk number to use as the deployment target.')] [System.UInt32] $DiskNumber, [Parameter(Mandatory = $false)] [System.Collections.IDictionary] $EnvParameters, [Parameter(Mandatory = $false)] [System.Management.Automation.SwitchParameter] $Force, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [System.String] $ProfileName = 'default', [Parameter(Mandatory = $false, HelpMessage = 'Optional manufacturer override used for driver pack selection.')] [System.String] $OSDManufacturer, [Parameter(Mandatory = $false, HelpMessage = 'Optional model override used for driver pack selection.')] [System.String] $OSDModel, [Parameter(Mandatory = $false, HelpMessage = 'Optional product/system ID override used for driver pack selection.')] [System.String] $OSDProduct, [Parameter(Mandatory = $false, HelpMessage = 'Mock/testing processor architecture override used for deployment selection.')] [ValidateNotNullOrEmpty()] [ValidateSet('amd64', 'arm64')] [System.String] $ProcessorArchitecture, [Parameter(Mandatory = $false, HelpMessage = 'Operating system name for deployment selection.')] [ValidateNotNullOrEmpty()] [System.String] $OperatingSystem, [Parameter(Mandatory = $false, HelpMessage = 'Operating system edition for deployment selection.')] [ValidateNotNullOrEmpty()] [System.String] $OSEdition, [Parameter(Mandatory = $false, HelpMessage = 'Operating system activation channel for deployment selection.')] [ValidateNotNullOrEmpty()] [System.String] $OSActivation, [Parameter(Mandatory = $false, HelpMessage = 'Operating system language code for deployment selection.')] [ValidateNotNullOrEmpty()] [ValidateSet( 'ar-sa', 'bg-bg', 'cs-cz', 'da-dk', 'de-de', 'el-gr', 'en-gb', 'en-us', 'es-es', 'es-mx', 'et-ee', 'fi-fi', 'fr-ca', 'fr-fr', 'he-il', 'hr-hr', 'hu-hu', 'it-it', 'ja-jp', 'ko-kr', 'lt-lt', 'lv-lv', 'nb-no', 'nl-nl', 'pl-pl', 'pt-br', 'pt-pt', 'ro-ro', 'ru-ru', 'sk-sk', 'sl-si', 'sr-latn-rs', 'sv-se', 'th-th', 'tr-tr', 'uk-ua', 'zh-cn', 'zh-tw' )] [System.String] $OSLanguageCode ) $ErrorActionPreference = 'Stop' #================================================= # Get module details # $ModuleVersion = $($MyInvocation.MyCommand.Module.Version) Write-Host -ForegroundColor DarkGray "[$(Get-Date -format s)] [INFO] [$($MyInvocation.MyCommand.Name)]" #================================================= # OSDCloud Env override layer # Assemble $global:OSDCloudEnv early so initial property resolution can consume # values from the selected profile and parameter overrides. <# if (Get-Command -Name 'Initialize-OSDCloudEnv' -ErrorAction Ignore) { Initialize-OSDCloudEnv -Parameters $EnvParameters -ProfileName $ProfileName | Out-Null } #> #================================================= # Dependencies # Make sure curl.exe is present and throw if not if (-not (Get-Command -Name 'curl.exe' -ErrorAction Ignore)) { throw "[$(Get-Date -format s)] [$($MyInvocation.MyCommand.Name)] OSDCloud requires 'curl.exe' which is not available on this system. Please ensure curl.exe is available in the system PATH." } # Preserve caller-specified OS values so they can be applied after workflow defaults are loaded. $requestedOSValues = @{} foreach ($requestedOSParameterName in 'OperatingSystem', 'OSEdition', 'OSActivation', 'OSLanguageCode') { if ($PSBoundParameters.ContainsKey($requestedOSParameterName)) { $requestedOSValues[$requestedOSParameterName] = [System.String]$PSBoundParameters[$requestedOSParameterName] } } #================================================= # Initialize if (-not ($global:OSDCoreDevice)) { Initialize-OSDCoreDevice } Initialize-OSDCoreCache #================================================= #region OSArchitecture if ($ProcessorArchitecture -and -not [string]::IsNullOrWhiteSpace($ProcessorArchitecture)) { $global:OSDCoreDevice.ProcessorArchitecture = $ProcessorArchitecture } # Resolve the effective architecture from OSDCoreDevice and normalize aliases. $processorArchitecture = if (-not [string]::IsNullOrWhiteSpace($global:OSDCoreDevice.ProcessorArchitecture)) { $global:OSDCoreDevice.ProcessorArchitecture } else { $env:PROCESSOR_ARCHITECTURE } switch -Regex ($processorArchitecture) { '^(amd64|x64)$' { $processorArchitecture = 'amd64'; break } '^arm64$' { $processorArchitecture = 'arm64'; break } default { throw "[$(Get-Date -format s)] [$($MyInvocation.MyCommand.Name)] Unsupported processor architecture '$processorArchitecture'. Expected amd64 or arm64." } } #endregion #================================================= # CoreDriverPacks Initialize-ModuleCoreDriverPacks -OSDManufacturer $OSDManufacturer -ProcessorArchitecture $processorArchitecture $global:OSDCoreDriverPacks = $global:ModuleCoreDriverPacks | Where-Object { $_.OSArchitecture -eq $processorArchitecture } Write-Host -ForegroundColor DarkGray "[$(Get-Date -format s)] [INFO] Ready: OSDCoreDriverPacks" #================================================= # CoreOperatingSystems $ModuleName = $($MyInvocation.MyCommand.Module.Name) if ($ModuleName -eq 'OSD') { $global:OSDCoreOperatingSystems = Get-OSDCoreOperatingSystems | Where-Object { $_.Architecture -match $processorArchitecture } Write-Host -ForegroundColor DarkGray "[$(Get-Date -format s)] [INFO] Ready: OSDCoreOperatingSystems" } elseif ($ModuleName -eq 'OSDCloud') { $global:OSDCoreOperatingSystems = Get-OSDCloudCoreOperatingSystems | Where-Object { $_.OSArchitecture -match $processorArchitecture } Write-Host -ForegroundColor DarkGray "[$(Get-Date -format s)] [INFO] Ready: OSDCoreOperatingSystems" } else { throw "[$(Get-Date -format s)] [$($MyInvocation.MyCommand.Name)] Unable to load core operating systems provider command." } #================================================= # OSDCloudDeploy $global:OSDCloudDeploy = $null $global:OSDCloudDeploy = [pscustomobject][ordered]@{ #CoreDriverPacks = [array]$global:ModuleCoreDriverPacks #CoreOperatingSystems = $global:OSDCoreOperatingSystems DeploymentDisk = $null DeploymentDiskNumber = $null DriverPackName = $null DriverPackCacheObject = $null DriverPackCloudObject = $null DriverPackCloudTest = $false Force = $Force.IsPresent Function = $($MyInvocation.MyCommand.Name) LaunchMethod = 'OSDCloudWorkflow' Module = $($MyInvocation.MyCommand.Module.Name) OperatingSystemCacheObject = $null OperatingSystemCloudObject = $null OperatingSystemCloudTest = $false OperatingSystem = $null OperatingSystemValues = $null OSArchitecture = $processorArchitecture OSActivation = $OSActivation OSActivationValues = $null OSBuild = $null OSBuildVersion = $null OSEdition = $null OSEditionId = $null OSEditionValues = $null OSLanguageCode = $null OSLanguageCodeValues = $null OSVersion = $OSVersion SkipFirmwareUpdate = $false TimeStart = $null WorkflowName = $WorkflowName WorkflowTaskName = $null WorkflowTaskObject = $null WorkflowTasks = $null # DriverFolderName = $null # DriverFolderNames = @() # DriverFolderPath = $null # DriverFolderPaths = @() # DriverFolderSelections = @() # ImageFileName = $ImageFileName # ImageFileUrl = $ImageFileUrl # LocalImageFileInfo = $null # LocalImageFilePath = $null # LocalImageName = $null # OperatingSystemObject = $OperatingSystemObject } #================================================= #region OSDCoreDevice Manufacturer, Model, Product overrides if ($OSDManufacturer -and -not [string]::IsNullOrWhiteSpace($OSDManufacturer)) { $global:OSDCoreDevice.OSDManufacturer = $OSDManufacturer } if ($OSDModel -and -not [string]::IsNullOrWhiteSpace($OSDModel)) { $global:OSDCoreDevice.OSDModel = $OSDModel } if ($OSDProduct -and -not [string]::IsNullOrWhiteSpace($OSDProduct)) { $global:OSDCoreDevice.OSDProduct = $OSDProduct } #================================================= # Refactor variables for deployment workflow initialization $OSDManufacturer = $global:OSDCoreDevice.OSDManufacturer $OSDModel = $global:OSDCoreDevice.OSDModel $OSDProduct = $global:OSDCoreDevice.OSDProduct #endregion #================================================= #region OSDCloudDeploy.DeploymentDisk $getDiskNumber = { param ($Disk) if ($Disk.PSObject.Properties.Match('Number').Count -gt 0) { $Disk.Number } elseif ($Disk.PSObject.Properties.Match('DiskNumber').Count -gt 0) { $Disk.DiskNumber } } $getDiskName = { param ($Disk) if ($Disk.PSObject.Properties.Match('FriendlyName').Count -gt 0) { $Disk.FriendlyName } else { 'Unknown' } } $getDiskSize = { param ($Disk) if ($Disk.PSObject.Properties.Match('Size').Count -gt 0) { "$([math]::Round($Disk.Size / 1GB, 2)) GB" } else { 'Unknown size' } } $localDisks = @($global:OSDCoreDevice.LocalDisk) if ($PSBoundParameters.ContainsKey('DiskNumber')) { $selectedDeploymentDisk = $localDisks | Where-Object { $localDiskNumber = & $getDiskNumber $_ $null -ne $localDiskNumber -and [System.UInt32]$localDiskNumber -eq $DiskNumber } | Select-Object -First 1 if (-not $selectedDeploymentDisk) { $availableLocalDiskDetails = @( $localDisks | ForEach-Object { $availableDiskNumber = & $getDiskNumber $_ $availableDiskName = & $getDiskName $_ $availableDiskSize = & $getDiskSize $_ "$availableDiskNumber ($availableDiskName, $availableDiskSize)" } ) $availableLocalDiskMessage = if ($availableLocalDiskDetails.Count -gt 0) { $availableLocalDiskDetails -join ', ' } else { 'None' } throw "[$(Get-Date -format s)] [$($MyInvocation.MyCommand.Name)] DiskNumber '$DiskNumber' is not a valid local deployment disk. Valid DiskNumber values: $availableLocalDiskMessage" } $tempDeploymentDisk = $selectedDeploymentDisk } else { $selectedDeploymentDisk = $localDisks | Select-Object -First 1 if ($selectedDeploymentDisk) { $tempDeploymentDisk = $selectedDeploymentDisk } } if ($tempDeploymentDisk) { $tempDeploymentDiskNumber = & $getDiskNumber $tempDeploymentDisk } if ($tempDeploymentDisk) { $deploymentDiskName = & $getDiskName $tempDeploymentDisk $deploymentDiskSize = & $getDiskSize $tempDeploymentDisk Write-Host -ForegroundColor DarkGreen "[$(Get-Date -format s)] [INFO] DiskNumber is automatically set to $tempDeploymentDiskNumber [$deploymentDiskName] with size $deploymentDiskSize." $otherLocalDisks = @($global:OSDCoreDevice.LocalDisk | Where-Object { $localDiskNumber = & $getDiskNumber $_ $localDiskNumber -ne $tempDeploymentDiskNumber }) foreach ($localDisk in $otherLocalDisks) { $localDiskNumber = & $getDiskNumber $localDisk $localDiskName = & $getDiskName $localDisk $localDiskSize = & $getDiskSize $localDisk Write-Host -ForegroundColor DarkGray "[$(Get-Date -format s)] [INFO] DiskNumber $localDiskNumber [$localDiskName] with size $localDiskSize was not selected for deployment." } } else { throw "[$(Get-Date -format s)] [$($MyInvocation.MyCommand.Name)] Unable to determine Deployment Disk. Please check your system configuration." } $global:OSDCloudDeploy.DeploymentDisk = $tempDeploymentDisk $global:OSDCloudDeploy.DeploymentDiskNumber = [System.UInt32]$tempDeploymentDiskNumber #endregion #================================================= #region DriverPacks if ($global:ModuleCoreDriverPacks) { $DriverPackCloudObject = $global:ModuleCoreDriverPacks | Where-Object { $_.SystemId -match $OSDProduct } | Select-Object -First 1 } Write-Host -ForegroundColor Gray "[$(Get-Date -format s)] [INFO] OSDManufacturer: $OSDManufacturer" Write-Host -ForegroundColor Gray "[$(Get-Date -format s)] [INFO] OSDModel: $OSDModel" Write-Host -ForegroundColor Gray "[$(Get-Date -format s)] [INFO] OSDProduct: $OSDProduct" if ($DriverPackCloudObject) { $global:OSDCloudDeploy.DriverPackCloudObject = $DriverPackCloudObject $global:OSDCloudDeploy.DriverPackName = $DriverPackCloudObject.Name Write-Host -ForegroundColor Gray "[$(Get-Date -format s)] [INFO] DriverPack: $($global:OSDCloudDeploy.DriverPackName)" Write-Host -ForegroundColor Gray "[$(Get-Date -format s)] [INFO] DriverPack Url: $($DriverPackCloudObject.Url)" } #================================================= # DriverPackCloudTest if ($DriverPackCloudObject) { Write-Host -ForegroundColor DarkGray "[$(Get-Date -format s)] [INFO] Test DriverPack CloudObject." $global:OSDCloudDeploy.DriverPackCloudTest = Test-OSDCoreDriverPackCloudObject -DriverPackCloudObject $DriverPackCloudObject if ($global:OSDCloudDeploy.DriverPackCloudTest) { Write-Host -ForegroundColor DarkGreen "[$(Get-Date -format s)] [INFO] DriverPack is available online and ready to downloaded." } else { Write-Host -ForegroundColor DarkYellow "[$(Get-Date -format s)] [WARN] DriverPack URL is not reachable online and cannot be downloaded." } # Driver pack catalogs use either HashMD5 or MD5Hash depending on the source. $expectedDriverPackHashMD5 = $null if ($DriverPackCloudObject.PSObject.Properties.Match('HashMD5').Count -gt 0) { $expectedDriverPackHashMD5 = [string]$DriverPackCloudObject.HashMD5 } elseif ($DriverPackCloudObject.PSObject.Properties.Match('MD5Hash').Count -gt 0) { $expectedDriverPackHashMD5 = [string]$DriverPackCloudObject.MD5Hash } # Check whether the selected driver pack is already present in the cache inventory. $DriverPackCacheObject = Get-OSDCoreDriverPackCacheObject -DriverPackCloudObject $DriverPackCloudObject if ($DriverPackCacheObject) { Write-Host -ForegroundColor DarkGray "[$(Get-Date -format s)] [INFO] Test DriverPack CacheObject." # Verify cached driver pack integrity when the catalog includes an MD5 hash. if (-not [string]::IsNullOrWhiteSpace($expectedDriverPackHashMD5)) { $actualDriverPackHashMD5 = (Get-FileHash -Path $DriverPackCacheObject.FullName -Algorithm MD5 -ErrorAction Stop).Hash if ($actualDriverPackHashMD5 -ne $expectedDriverPackHashMD5.Trim()) { throw "[$(Get-Date -format s)] DriverPack MD5 hash mismatch for $($DriverPackCacheObject.FullName). Expected $($expectedDriverPackHashMD5.Trim()), found $actualDriverPackHashMD5." } Write-Host -ForegroundColor DarkGreen "[$(Get-Date -format s)] [INFO] DriverPack is saved in cache and MD5 hash verified." } else { Write-Host -ForegroundColor DarkGreen "[$(Get-Date -format s)] [INFO] DriverPack is saved in cache." } Write-Host -ForegroundColor DarkGray "[$(Get-Date -format s)] [INFO] $($DriverPackCacheObject.FullName)" $global:OSDCloudDeploy.DriverPackCacheObject = $DriverPackCacheObject $global:OSDCloudDeploy.DriverPackCloudTest = $true } else { Write-Host -ForegroundColor DarkYellow "[$(Get-Date -format s)] [WARN] DriverPack is not available in the offline cache." $DriverPackCacheObject = $null } # $DriverPackCloudObject | Format-List | Out-Host } else { Write-Host -ForegroundColor DarkYellow "[$(Get-Date -format s)] [WARN] OSDCoreDriverPackCloudObject is not set." Write-Host -ForegroundColor DarkYellow "[$(Get-Date -format s)] [WARN] OSDCloud will not apply a DriverPack for this deployment." $global:OSDCloudDeploy.DriverPackCacheObject = $null $global:OSDCloudDeploy.DriverPackCloudObject = $null $global:OSDCloudDeploy.DriverPackCloudTest = $false $global:OSDCloudDeploy.DriverPackName = $null } #endregion #================================================= # OSDCloudWorkflowSettingsOS # This function will read a configuration file and store it in $OSDCloudWorkflowSettingsOS Initialize-OSDCloudWorkflowSettingsOS -WorkflowName $WorkflowName -Architecture $global:OSDCloudDeploy.OSArchitecture # Apply workflow OS constraints to the loaded catalog for this architecture. $allowedOperatingSystems = @($global:OSDCloudWorkflowSettingsOS.OperatingSystem.values | Where-Object { -not [string]::IsNullOrWhiteSpace([string]$_) }) $allowedOSActivations = @($global:OSDCloudWorkflowSettingsOS.OSActivation.values | Where-Object { -not [string]::IsNullOrWhiteSpace([string]$_) }) $allowedOSEditionObjects = @($global:OSDCloudWorkflowSettingsOS.OSEdition.values) $allowedOSEditions = @($allowedOSEditionObjects | ForEach-Object { [string]$_.Edition } | Where-Object { -not [string]::IsNullOrWhiteSpace($_) }) $allowedOSLanguageCodes = @($global:OSDCloudWorkflowSettingsOS.OSLanguageCode.values | Where-Object { -not [string]::IsNullOrWhiteSpace([string]$_) }) $global:OSDCoreOperatingSystems = @( $global:OSDCoreOperatingSystems | Where-Object { ($allowedOperatingSystems.Count -eq 0 -or $allowedOperatingSystems -contains [string]$_.OperatingSystem) -and ($allowedOSActivations.Count -eq 0 -or $allowedOSActivations -contains [string]$_.OSActivation) -and ($allowedOSLanguageCodes.Count -eq 0 -or $allowedOSLanguageCodes -contains [string]$_.OSLanguageCode) } ) if (-not $global:OSDCoreOperatingSystems) { throw "[$(Get-Date -format s)] [$($MyInvocation.MyCommand.Name)] No Operating Systems remain after applying workflow OS filters. Check workflow/$WorkflowName/ui/os.json values for OperatingSystem, OSActivation, and OSLanguageCode." } Write-Host -ForegroundColor DarkGray "[$(Get-Date -format s)] [INFO] Filtered OSDCoreOperatingSystems Count: $(@($global:OSDCoreOperatingSystems).Count)" #================================================= # $OperatingSystemCloudObject <# This global variable is used to store the selected operating system object from the catalog for use in deployment. A default should be selected based on this order of preference: 1. Parameter. 2. OSDCloudEnv override 3. Workflow default 4. First available in the filtered catalog #> # Solution: $preferredOperatingSystem = [string]$global:OSDCloudWorkflowSettingsOS.OperatingSystem.default $preferredOSEdition = [string]$global:OSDCloudWorkflowSettingsOS.OSEdition.default $preferredOSActivation = [string]$global:OSDCloudWorkflowSettingsOS.OSActivation.default $preferredOSLanguageCode = [string]$global:OSDCloudWorkflowSettingsOS.OSLanguageCode.default if ($global:OSDCloudEnv) { if (-not [string]::IsNullOrWhiteSpace([string]$global:OSDCloudEnv.OperatingSystem)) { $preferredOperatingSystem = [string]$global:OSDCloudEnv.OperatingSystem } if (-not [string]::IsNullOrWhiteSpace([string]$global:OSDCloudEnv.OSEdition)) { $preferredOSEdition = [string]$global:OSDCloudEnv.OSEdition } if (-not [string]::IsNullOrWhiteSpace([string]$global:OSDCloudEnv.OSActivation)) { $preferredOSActivation = [string]$global:OSDCloudEnv.OSActivation } if (-not [string]::IsNullOrWhiteSpace([string]$global:OSDCloudEnv.OSLanguageCode)) { $preferredOSLanguageCode = [string]$global:OSDCloudEnv.OSLanguageCode } } if (-not [string]::IsNullOrWhiteSpace($requestedOSValues['OperatingSystem'])) { $preferredOperatingSystem = $requestedOSValues['OperatingSystem'] } if (-not [string]::IsNullOrWhiteSpace($requestedOSValues['OSEdition'])) { $preferredOSEdition = $requestedOSValues['OSEdition'] } if (-not [string]::IsNullOrWhiteSpace($requestedOSValues['OSActivation'])) { $preferredOSActivation = $requestedOSValues['OSActivation'] } if (-not [string]::IsNullOrWhiteSpace($requestedOSValues['OSLanguageCode'])) { $preferredOSLanguageCode = $requestedOSValues['OSLanguageCode'] } if ($preferredOperatingSystem -notin $allowedOperatingSystems) { throw "[$(Get-Date -format s)] [$($MyInvocation.MyCommand.Name)] OperatingSystem '$preferredOperatingSystem' is not valid for workflow '$WorkflowName'. Valid values: $($allowedOperatingSystems -join ', ')" } if ($preferredOSEdition -notin $allowedOSEditions) { throw "[$(Get-Date -format s)] [$($MyInvocation.MyCommand.Name)] OSEdition '$preferredOSEdition' is not valid for workflow '$WorkflowName'. Valid values: $($allowedOSEditions -join ', ')" } if ($preferredOSLanguageCode -notin $allowedOSLanguageCodes) { throw "[$(Get-Date -format s)] [$($MyInvocation.MyCommand.Name)] OSLanguageCode '$preferredOSLanguageCode' is not valid for workflow '$WorkflowName'. Valid values: $($allowedOSLanguageCodes -join ', ')" } $resolvedPreferredOSActivation = Resolve-OSDCloudWorkflowOSActivation -OSEdition $preferredOSEdition -OSActivation $preferredOSActivation if ($resolvedPreferredOSActivation -ne $preferredOSActivation) { Write-Host -ForegroundColor DarkGray "[$(Get-Date -format s)] [INFO] OSEdition '$preferredOSEdition' requires OSActivation '$resolvedPreferredOSActivation'." $preferredOSActivation = $resolvedPreferredOSActivation } if ($preferredOSActivation -notin $allowedOSActivations) { throw "[$(Get-Date -format s)] [$($MyInvocation.MyCommand.Name)] OSEdition '$preferredOSEdition' requires OSActivation '$preferredOSActivation', which is not valid for workflow '$WorkflowName'. Valid values: $($allowedOSActivations -join ', ')" } $operatingSystemBuildVersionSort = @{ Expression = { try { [version]([string]$_.OSBuildVersion -replace '[^0-9\.]', '') } catch { [version]'0.0' } }; Descending = $true } $OperatingSystemCloudObject = $global:OSDCoreOperatingSystems | Where-Object { ([string]$_.OperatingSystem -ieq $preferredOperatingSystem) -and ([string]$_.OSActivation -ieq $preferredOSActivation) -and ([string]$_.OSLanguageCode -ieq $preferredOSLanguageCode) } | Sort-Object -Property $operatingSystemBuildVersionSort | Select-Object -First 1 if (-not $OperatingSystemCloudObject) { Write-Warning "[$(Get-Date -format s)] [$($MyInvocation.MyCommand.Name)] No exact operating system match was found for OperatingSystem '$preferredOperatingSystem', OSActivation '$preferredOSActivation', and OSLanguageCode '$preferredOSLanguageCode'. Falling back to the first available filtered catalog entry." $OperatingSystemCloudObject = $global:OSDCoreOperatingSystems | Sort-Object -Property $operatingSystemBuildVersionSort | Select-Object -First 1 } if (-not $OperatingSystemCloudObject) { throw "[$(Get-Date -format s)] [$($MyInvocation.MyCommand.Name)] Unable to set OperatingSystemCloudObject because no operating system entries are available in the filtered catalog." } #================================================= # OSDCoreOperatingSystems Verify if ($OperatingSystemCloudObject) { $OperatingSystemCloudObject | Export-Clixml -Path (Join-Path -Path $env:TEMP -ChildPath 'OperatingSystemCloudObject.xml') -Force Write-Host -ForegroundColor DarkGray "[$(Get-Date -format s)] [INFO] Test OperatingSystem CloudObject." # Confirm the selected operating system download URL before offering cache download work. $global:OSDCloudDeploy.OperatingSystemCloudTest = Test-OperatingSystemCloudObject -OperatingSystemCloudObject $OperatingSystemCloudObject if ($global:OSDCloudDeploy.OperatingSystemCloudTest) { Write-Host -ForegroundColor DarkGreen "[$(Get-Date -format s)] [INFO] OperatingSystem is available online and ready to downloaded." } else { Write-Host -ForegroundColor DarkYellow "[$(Get-Date -format s)] [WARN] OperatingSystem URL is not reachable online and cannot be downloaded." } # Prefer SHA256 when the catalog provides it, and fall back to SHA1 for older entries. $expectedOperatingSystemHash = $null $expectedOperatingSystemHashAlgorithm = $null if (-not [string]::IsNullOrWhiteSpace([string]$OperatingSystemCloudObject.SHA256)) { $expectedOperatingSystemHash = [string]$OperatingSystemCloudObject.SHA256 $expectedOperatingSystemHashAlgorithm = 'SHA256' } elseif (-not [string]::IsNullOrWhiteSpace([string]$OperatingSystemCloudObject.SHA1)) { $expectedOperatingSystemHash = [string]$OperatingSystemCloudObject.SHA1 $expectedOperatingSystemHashAlgorithm = 'SHA1' } # Check whether the selected OS payload is already present in the USB cache inventory. $OperatingSystemCacheObject = Get-OSDCoreOperatingSystemCacheObject -OperatingSystemCloudObject $OperatingSystemCloudObject if ($OperatingSystemCacheObject) { $OperatingSystemCacheObject | Export-Clixml -Path (Join-Path -Path $env:TEMP -ChildPath 'OSDCoreOperatingSystemCacheObject.xml') -Force Write-Host -ForegroundColor DarkGray "[$(Get-Date -format s)] [INFO] Test OperatingSystem CacheObject." # Verify the cached payload before treating it as ready. if (-not [string]::IsNullOrWhiteSpace($expectedOperatingSystemHash)) { $actualOperatingSystemHash = (Get-FileHash -Path $OperatingSystemCacheObject.FullName -Algorithm $expectedOperatingSystemHashAlgorithm -ErrorAction Stop).Hash if ($actualOperatingSystemHash -ne $expectedOperatingSystemHash.Trim()) { throw "[$(Get-Date -format s)] OSDCoreOperatingSystemCloudObject $expectedOperatingSystemHashAlgorithm hash mismatch for $($OperatingSystemCacheObject.FullName). Expected $($expectedOperatingSystemHash.Trim()), found $actualOperatingSystemHash." } Write-Host -ForegroundColor DarkGray "[$(Get-Date -format s)] [INFO] OperatingSystem is saved in cache and $expectedOperatingSystemHashAlgorithm hash verified." } else { Write-Host -ForegroundColor DarkGray "[$(Get-Date -format s)] [INFO] OperatingSystem cached file hash was not verified because no hash property was available." } Write-Host -ForegroundColor DarkGray "[$(Get-Date -format s)] [INFO] $($OperatingSystemCacheObject.FullName)" $global:OSDCloudDeploy.OperatingSystemCacheObject = $OperatingSystemCacheObject } else { Write-Host -ForegroundColor DarkYellow "[$(Get-Date -format s)] [WARN] OperatingSystem is not available in the offline cache." $global:OSDCloudDeploy.OperatingSystemCacheObject = $null } # Build a display object that supports both OSD and OSDCloud property shapes. $selectedOperatingSystemName = if ($OperatingSystemCloudObject.Id) { $OperatingSystemCloudObject.Id } else { $OperatingSystemCloudObject.Name } $selectedOperatingSystemUrl = if ($OperatingSystemCloudObject.FilePath) { $OperatingSystemCloudObject.FilePath } else { $OperatingSystemCloudObject.Url } $selectedOperatingSystemSha1 = if ($OperatingSystemCloudObject.Sha1) { $OperatingSystemCloudObject.Sha1 } else { $OperatingSystemCloudObject.SHA1 } $selectedOperatingSystemSha256 = if ($OperatingSystemCloudObject.Sha256) { $OperatingSystemCloudObject.Sha256 } else { $OperatingSystemCloudObject.SHA256 } # Write-Host -ForegroundColor DarkCyan "[$(Get-Date -format s)] OSDCoreOperatingSystemCloudObject:" $tempOperatingSystemDisplay = [ordered]@{ Name = [string]$selectedOperatingSystemName FileName = [string]$OperatingSystemCloudObject.FileName Url = [string]$selectedOperatingSystemUrl } if (-not [string]::IsNullOrWhiteSpace([string]$selectedOperatingSystemSha256)) { $tempOperatingSystemDisplay['SHA256'] = [string]$selectedOperatingSystemSha256 } elseif (-not [string]::IsNullOrWhiteSpace([string]$selectedOperatingSystemSha1)) { $tempOperatingSystemDisplay['SHA1'] = [string]$selectedOperatingSystemSha1 } $tempOSDCoreOperatingSystemCloudObject = [pscustomobject]$tempOperatingSystemDisplay $tempOSDCoreOperatingSystemCloudObject | Format-List | Out-Host $global:OSDCloudDeploy.OperatingSystemCloudObject = $OperatingSystemCloudObject } #================================================= # OSDCloudWorkflowTasks # If $WorkflowName is not default, display a message that this Workflow is for Beta or Testing purposes only if ($WorkflowName -ne 'default') { Write-Warning "[$(Get-Date -format s)] The workflow '$WorkflowName' is for Beta testing purposes only." } Initialize-OSDCloudWorkflowTasks -WorkflowName $WorkflowName # Make sure at least one workflow task is defined if (-not $global:OSDCloudWorkflowTasks) { throw "[$(Get-Date -format s)] [$($MyInvocation.MyCommand.Name)] Initialize-DeployOSDCloud requires at least one valid workflow task. Please check your OSDCloud Workflow Tasks." } $global:OSDCloudDeploy.WorkflowTasks = [array]$global:OSDCloudWorkflowTasks $global:OSDCloudDeploy.WorkflowTaskObject = $global:OSDCloudDeploy.WorkflowTasks | Select-Object -First 1 $global:OSDCloudDeploy.WorkflowTaskName = $global:OSDCloudDeploy.WorkflowTaskObject.name #================================================= # Set initial Operating System <# Id : Windows 11 25H2 amd64 Retail en-gb 26200.7462 OperatingSystem : Windows 11 25H2 OSVersion : 25H2 OSArchitecture : amd64 OSActivation : Retail LanguageCode : en-gb Language : English (United Kingdom) OSBuild : 26200 OSBuildVersion : 26200.7462 Size : 5626355066 Sha1 : Sha256 : 566a518dc46ba5ea401381810751a8abcfe7d012b2f81c9709b787358c606926 FileName : 26200.7462.251207-0044.25h2_ge_release_svc_refresh_CLIENTCONSUMER_RET_x64FRE_en-gb.esd FilePath : http://dl.delivery.mp.microsoft.com/filestreamingservice/files/79a3f5e0-d04d-4689-a5d4-3ea35f8b189a/26200.7462.251207-0044.25h2_ge_release_svc_refresh_CLIENTCONSUMER_RET_x64FRE_en-gb.esd #> #================================================= # OperatingSystemObject $OperatingSystemObject = $global:OSDCloudDeploy.OperatingSystemCloudObject if (-not $OperatingSystemObject) { throw "[$(Get-Date -format s)] [$($MyInvocation.MyCommand.Name)] Unable to initialize deployment state because OperatingSystemCloudObject is not set." } #================================================= # OperatingSystem $OperatingSystem = if ($OperatingSystemObject.OperatingSystem) { [string]$OperatingSystemObject.OperatingSystem } else { $preferredOperatingSystem } $global:OSDCloudDeploy.OperatingSystem = $OperatingSystem $global:OSDCloudDeploy.OperatingSystemValues = [array]$allowedOperatingSystems #================================================= # OSActivation $OSActivation = if ($OperatingSystemObject.OSActivation) { [string]$OperatingSystemObject.OSActivation } elseif ($OperatingSystemObject.Activation) { [string]$OperatingSystemObject.Activation } else { $preferredOSActivation } $global:OSDCloudDeploy.OSActivation = $OSActivation $global:OSDCloudDeploy.OSActivationValues = [array]$allowedOSActivations #================================================= # OSBuild $global:OSDCloudDeploy.OSBuild = if ($OperatingSystemObject.OSBuild) { [string]$OperatingSystemObject.OSBuild } else { [string]$OperatingSystemObject.Build } #================================================= # OSBuildVersion $global:OSDCloudDeploy.OSBuildVersion = if ($OperatingSystemObject.OSBuildVersion) { [string]$OperatingSystemObject.OSBuildVersion } else { [string]$OperatingSystemObject.Build } #================================================= # OSEdition $OSEdition = $preferredOSEdition $OSEditionValues = [array]$allowedOSEditionObjects $OSEditionObject = $OSEditionValues | Where-Object { $_.Edition -eq $OSEdition } | Select-Object -First 1 if (-not $OSEditionObject) { $validOSEditions = $OSEditionValues | ForEach-Object { $_.Edition } throw "[$(Get-Date -format s)] [$($MyInvocation.MyCommand.Name)] OSEdition '$OSEdition' is not valid for workflow '$WorkflowName'. Valid values: $($validOSEditions -join ', ')" } if ([string]::IsNullOrWhiteSpace([string]$OSEditionObject.EditionId)) { throw "[$(Get-Date -format s)] [$($MyInvocation.MyCommand.Name)] OSEdition '$OSEdition' does not have a valid EditionId in workflow '$WorkflowName'." } $global:OSDCloudDeploy.OSEdition = $OSEdition $global:OSDCloudDeploy.OSEditionValues = $OSEditionValues $global:OSDCloudDeploy.OSEditionId = $OSEditionObject.EditionId #================================================= # OSLanguageCode $OSLanguageCode = if ($OperatingSystemObject.OSLanguageCode) { [string]$OperatingSystemObject.OSLanguageCode } elseif ($OperatingSystemObject.Language) { [string]$OperatingSystemObject.Language } else { $preferredOSLanguageCode } $global:OSDCloudDeploy.OSLanguageCode = $OSLanguageCode $global:OSDCloudDeploy.OSLanguageCodeValues = [array]$allowedOSLanguageCodes #================================================= # OSVersion $OSVersion = if ($OperatingSystemObject.OSVersion) { [string]$OperatingSystemObject.OSVersion } elseif ($OperatingSystemObject.ReleaseID) { [string]$OperatingSystemObject.ReleaseID } else { ($OperatingSystem -split ' ')[2] } $global:OSDCloudDeploy.OSVersion = $OSVersion #================================================= # OSDCloud Env override layer # Apply the pre-assembled overrides onto $global:OSDCloudDeploy so they take effect # everywhere. <# if (Get-Command -Name 'Set-OSDCloudEnvOverride' -ErrorAction Ignore) { Set-OSDCloudEnvOverride -Target $global:OSDCloudDeploy -ResolveOperatingSystem -AddMissingKeys } #> $global:OSDCloudDeploy | Export-Clixml -Path (Join-Path -Path $env:TEMP -ChildPath 'OSDCloudDeploy.xml') -Force Write-Host -ForegroundColor DarkGray "[$(Get-Date -format s)] [INFO] Ready: OSDCloudDeploy" #================================================= } |