Skip to content

Commit 9d64fcb

Browse files
Support offline OS and driver catalogs, add post-network script execution, and improve download reliability
- Add support for importing offline OS catalogs in - Get-OSDCloudOperatingSystems.ps1 - Get-OSDCloudOperatingSystemsIndexMap.ps1 - Get-OSDCloudOperatingSystemsIndexes.ps1 - Add offline driver catalog support in OSDCloud.DriverPack.ps1 - Add post-network script execution and optional supression of module auto-update in - Initialize-OSDCloudStartNet.ps1 - OSDCloudTemplate.ps1 - Since PR #316 adresses a simillar improvement, I've removed my changes. (Improve Save-WebFile.ps1 by checking HTTP headers before download)
1 parent e1b95ee commit 9d64fcb

File tree

7 files changed

+120
-79
lines changed

7 files changed

+120
-79
lines changed

Public/Functions/Other/Save-WebFile.ps1

Lines changed: 15 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ function Save-WebFile {
1111
[OutputType([System.IO.FileInfo])]
1212
param
1313
(
14-
[Parameter(Position = 0, Mandatory, ValueFromPipelineByPropertyName)]
14+
[Parameter(Position=0, Mandatory, ValueFromPipelineByPropertyName)]
1515
[Alias('FileUri')]
1616
[System.String]
1717
$SourceUrl,
@@ -44,7 +44,8 @@ function Save-WebFile {
4444
#=================================================
4545
# DestinationDirectory
4646
#=================================================
47-
if (Test-Path "$DestinationDirectory") {
47+
if (Test-Path "$DestinationDirectory")
48+
{
4849
Write-Verbose "Directory already exists at $DestinationDirectory"
4950
}
5051
else {
@@ -61,8 +62,8 @@ function Save-WebFile {
6162
Remove-Item -Path $DestinationNewItem.FullName -Force | Out-Null
6263
}
6364
else {
64-
Write-Warning 'Unable to write to Destination Directory'
65-
break
65+
Write-Warning "Unable to write to Destination Directory"
66+
Break
6667
}
6768
#=================================================
6869
# DestinationName
@@ -82,8 +83,8 @@ function Save-WebFile {
8283
#=================================================
8384
# OverWrite
8485
#=================================================
85-
if ((-not ($PSBoundParameters['Overwrite'])) -and (Test-Path $DestinationFullName)) {
86-
Write-Verbose 'DestinationFullName already exists'
86+
if ((-NOT ($PSBoundParameters['Overwrite'])) -and (Test-Path $DestinationFullName)) {
87+
Write-Verbose "DestinationFullName already exists"
8788
Get-Item $DestinationFullName -Force
8889
}
8990
else {
@@ -115,57 +116,17 @@ function Save-WebFile {
115116
else {
116117
Write-Verbose "cURL Source: $SourceUrl"
117118
Write-Verbose "Destination: $DestinationFullName"
118-
119-
Write-Verbose 'Requesing HTTP HEAD to get Content-Length and Accept-Ranges header'
120-
$remote = Invoke-WebRequest -UseBasicParsing -Method Head -Uri $SourceUrl
121-
$remoteLength = $remote.Headers.'Content-Length'
122-
$remoteAcceptsRanges = ($remote.Headers.'Accept-Ranges' | Select-Object -First 1) -eq 'bytes'
123-
124-
$curlCommandExpression = "& curl.exe --insecure --location --output `"$DestinationFullName`" --url `"$SourceUrl`""
125-
126-
if ($host.name -match 'PowerShell ISE Host') {
127-
#PowerShell ISE will display a NativeCommandError, so progress will not be displayed
128-
$Quiet = Invoke-Expression ($curlCommandExpression + ' 2>&1')
129-
}
130-
else {
131-
Invoke-Expression $curlCommandExpression
132-
}
133-
134-
#=================================================
135-
# Continue interrupted download
136-
#=================================================
137-
if (Test-Path $DestinationFullName) {
138-
$localExists = $true
139-
}
140-
141-
$RetryDelaySeconds = 1
142-
$MaxRetryCount = 10
143-
$RetryCount = 0
144-
while (
145-
$localExists `
146-
-and ((Get-Item $DestinationFullName).Length -lt $remoteLength) `
147-
-and $remoteAcceptsRanges `
148-
-and ($RetryCount -lt $MaxRetryCount)
149-
) {
150-
Write-Verbose "Download is incomplete, remote server accepts ranges, will retry in $RetryDelaySeconds second(s)"
151-
Start-Sleep -Seconds $RetryDelaySeconds
152-
$RetryDelaySeconds *= 2 # retry with exponential backoff
153-
$RetryCount += 1
154-
$curlCommandExpression = "& curl.exe --insecure --location --continue-at - --output `"$DestinationFullName`" --url `"$SourceUrl`""
155-
156-
if ($host.name -match 'PowerShell ISE Host') {
157-
#PowerShell ISE will display a NativeCommandError, so progress will not be displayed
158-
$Quiet = Invoke-Expression ($curlCommandExpression + ' 2>&1')
119+
$Headers = Invoke-Expression "& curl.exe --head --silent --insecure --location --url `"$SourceUrl`""
120+
if ($Headers[0] -match "200.+OK") {
121+
if ($host.name -match 'ConsoleHost') {
122+
Invoke-Expression "& curl.exe --insecure --location --output `"$DestinationFullName`" --url `"$SourceUrl`""
159123
}
160124
else {
161-
Invoke-Expression $curlCommandExpression
125+
#PowerShell ISE will display a NativeCommandError, so progress will not be displayed
126+
$Quiet = Invoke-Expression "& curl.exe --insecure --location --output `"$DestinationFullName`" --url `"$SourceUrl`" 2>&1"
162127
}
163-
}
164-
165-
if ($localExists -and ((Get-Item $DestinationFullName).Length -lt $remoteLength)) {
166-
Write-Verbose "Download is incomplete after $RetryCount retries."
167-
Write-Warning "Could not download $DestinationFullName"
168-
$null
128+
} else {
129+
Write-Warning "Header status: $($headers[0])"
169130
}
170131
}
171132
#=================================================

Public/OSDCloudDriverPack/OSDCloud.DriverPack.ps1

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,17 @@ function Get-OSDCloudDriverPacks {
6767
#>
6868
[CmdletBinding()]
6969
param ()
70-
$Results = Import-Clixml -Path "$(Get-OSDModulePath)\cache\driverpack-catalogs\build-driverpacks.xml"
70+
$DriverCatalogXML = Get-PSDrive -PSProvider FileSystem | Where-Object {$_.Name -ne 'C'} | ForEach-Object {
71+
Get-ChildItem "$($_.Root)OSDCloud\Catalogs" -Include "build-driverpacks.xml" -File -Force -Recurse -ErrorAction Ignore
72+
}
73+
if ($DriverCatalogXML) {
74+
foreach ($Item in $DriverCatalogXML) {
75+
Write-Warning "$($Item.FullName) is imported instead of the cache under $(Get-OSDModulePath)."
76+
$Results = Import-Clixml -Path $Item.FullName
77+
}
78+
} else {
79+
$Results = Import-Clixml -Path "$(Get-OSDModulePath)\cache\driverpack-catalogs\build-driverpacks.xml"
80+
}
7181
$Results
7282
}
7383
function Save-OSDCloudDriverPack {

Public/OSDCloudSetup/OSDCloudTemplate.ps1

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1014,7 +1014,8 @@ Windows Registry Editor Version 5.00
10141014
'Config\Scripts\SetupComplete',
10151015
'Config\Scripts\Shutdown',
10161016
'Config\Scripts\Startup',
1017-
'Config\Scripts\StartNet'
1017+
'Config\Scripts\StartNet',
1018+
'Config\Scripts\StartNet2'
10181019
)
10191020

10201021
if ($Name -match 'public') {

Public/OSDCloudTS/Get-OSDCloudOperatingSystems.ps1

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,18 @@ function Get-OSDCloudOperatingSystems {
1616
[System.String]
1717
$OSArch = 'x64'
1818
)
19-
$FullResults = Get-Content -Path "$(Get-OSDModulePath)\cache\archive-cloudoperatingsystems\CloudOperatingSystems.json" | ConvertFrom-Json
20-
if ($OSArch -eq 'x64'){
21-
$Results = $FullResults | Where-Object {$_.Architecture -eq "x64"}
19+
$OfflineCatalog = Get-PSDrive -PSProvider FileSystem | Where-Object {$_.Name -ne 'C'} | ForEach-Object {
20+
Get-ChildItem "$($_.Root)OSDCloud\Catalogs" -Include "CloudOperatingSystems.json" -File -Force -Recurse -ErrorAction Ignore
2221
}
23-
elseif ($OSArch -eq "arm64"){
24-
$Results = Get-Content -Path "$(Get-OSDModulePath)\cache\archive-cloudoperatingsystems\CloudOperatingSystemsARM64.json" | ConvertFrom-Json
22+
if ($OfflineCatalog) {
23+
foreach ($Item in $OfflineCatalog) {
24+
Write-Warning "$($Item.FullName) is imported instead of the cache under $(Get-OSDModulePath)."
25+
$FullResults = Get-Content -Path "$($Item.FullName)" | ConvertFrom-Json -ErrorAction "Stop"
26+
}
27+
$Results = $FullResults | Where-Object {$_.Architecture -eq $OSArch}
28+
} else {
29+
$FullResults = Get-Content -Path "$(Get-OSDModulePath)\cache\archive-cloudoperatingsystems\CloudOperatingSystems.json" | ConvertFrom-Json
30+
$Results = $FullResults | Where-Object {$_.Architecture -eq $OSArch}
2531
}
2632
$Results
2733
}

Public/OSDCloudTS/Get-OSDCloudOperatingSystemsIndexMap.ps1

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,19 @@ function Get-OSDCloudOperatingSystemsIndexMap {
2121
$OSArch = 'x64'
2222
)
2323

24-
$indexMapPath = "$(Get-OSDModulePath)\cache\archive-cloudoperatingindexmap\CloudOperatingIndexMap.json"
25-
$Results = Get-Content -Path $indexMapPath | ConvertFrom-Json
24+
$OfflineCatalog = Get-PSDrive -PSProvider FileSystem | Where-Object {$_.Name -ne 'C'} | ForEach-Object {
25+
Get-ChildItem "$($_.Root)OSDCloud\Catalogs" -Include "CloudOperatingIndexMap.json" -File -Force -Recurse -ErrorAction Ignore
26+
}
27+
if ($OfflineCatalog) {
28+
foreach ($Item in $OfflineCatalog) {
29+
Write-Warning "$($Item.FullName) is imported instead of the cache under $(Get-OSDModulePath)."
30+
$indexMapPath = (Get-Item -Path "$($Item.FullName)").FullName
31+
}
32+
} else {
33+
$indexMapPath = "$(Get-OSDCachePath)\archive-cloudoperatingindexmap\CloudOperatingIndexMap.json"
34+
}
35+
$Results = Get-Content -Path $indexMapPath -Encoding UTF8 | ConvertFrom-Json # as of OSD 25.6.10.1 encoding of the json is UTF8
2636
$Results = $Results | Where-Object { $_.Architecture -eq $OSArch }
2737

2838
return $Results
29-
}
39+
}

Public/OSDCloudTS/Get-OSDCloudOperatingSystemsIndexes.ps1

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,30 @@ function Get-OSDCloudOperatingSystemsIndexes {
1919
)
2020

2121
if ($OSArch -eq 'x64') {
22-
$Results = Get-Content -Path "$(Get-OSDModulePath)\cache\archive-cloudoperatingsystems\CloudOperatingSystemsIndexes.json" | ConvertFrom-Json
22+
$OfflineCatalog = Get-PSDrive -PSProvider FileSystem | Where-Object {$_.Name -ne 'C'} | ForEach-Object {
23+
Get-ChildItem "$($_.Root)OSDCloud\Catalogs" -Include "CloudOperatingSystemsIndexes.json" -File -Force -Recurse -ErrorAction Ignore
24+
}
25+
if ($OfflineCatalog) {
26+
foreach ($Item in $OfflineCatalog) {
27+
Write-Warning "$($Item.FullName) is imported instead of the cache under $(Get-OSDModulePath)."
28+
$Results = Get-Content -Path "$($Item.FullName)" | ConvertFrom-Json -ErrorAction "Stop"
29+
}
30+
} else {
31+
$Results = Get-Content -Path "$(Get-OSDCachePath)\archive-cloudoperatingsystems\CloudOperatingSystemsIndexes.json" | ConvertFrom-Json
32+
}
2333
}
2434
elseif ($OSArch -eq "ARM64") {
25-
$Results = Get-Content -Path "$(Get-OSDModulePath)\cache\archive-cloudoperatingsystems\CloudOperatingSystemsARM64Indexes.json" | ConvertFrom-Json
35+
$OfflineCatalog = Get-PSDrive -PSProvider FileSystem | Where-Object {$_.Name -ne 'C'} | ForEach-Object {
36+
Get-ChildItem "$($_.Root)OSDCloud\Catalogs" -Include "CloudOperatingSystemsARM64Indexes.json" -File -Force -Recurse -ErrorAction Ignore
37+
}
38+
if ($OfflineCatalog) {
39+
foreach ($Item in $OfflineCatalog) {
40+
Write-Warning "$($Item.FullName) is imported instead of the cache under $(Get-OSDModulePath)."
41+
$Results = Get-Content -Path "$($Item.FullName)" | ConvertFrom-Json -ErrorAction "Stop"
42+
}
43+
} else {
44+
$Results = Get-Content -Path "$(Get-OSDCachePath)\archive-cloudoperatingsystems\CloudOperatingSystemsARM64Indexes.json" | ConvertFrom-Json
45+
}
2646
}
2747

2848
return $Results

Public/OSDCloudTS/Initialize-OSDCloudStartnet.ps1

Lines changed: 46 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -142,20 +142,53 @@ function Initialize-OSDCloudStartnet {
142142
}
143143
}
144144

145-
# Check if the OSD Module in the PowerShell Gallery is newer than the installed version
146-
$TimeSpan = New-TimeSpan -Start $Global:StartnetStart -End (Get-Date)
147-
Write-Host -ForegroundColor DarkGray "$($TimeSpan.ToString("mm':'ss")) Updating OSD PowerShell Module"
148-
$PSModuleName = 'OSD'
149-
$InstalledModule = Get-Module -Name $PSModuleName -ListAvailable -ErrorAction Ignore | Sort-Object Version -Descending | Select-Object -First 1
150-
$GalleryPSModule = Find-Module -Name $PSModuleName -ErrorAction Ignore -WarningAction Ignore
151-
152-
# Install the OSD module if it is not installed or if the version is older than the gallery version
153-
if ($GalleryPSModule) {
154-
if (($GalleryPSModule.Version -as [version]) -gt ($InstalledModule.Version -as [version])) {
155-
Write-Host -ForegroundColor DarkGray "$PSModuleName $($GalleryPSModule.Version) [AllUsers]"
156-
Install-Module $PSModuleName -Scope AllUsers -Force -SkipPublisherCheck
157-
Import-Module $PSModuleName -Force
145+
Write-Host -ForegroundColor Cyan '[i] Config Post StartNet Scripts'
146+
$Global:ScriptStartNet2 = Get-PSDrive -PSProvider FileSystem | Where-Object { $_.Name -ne 'C' } | ForEach-Object {
147+
Write-Host -ForegroundColor DarkGray "$($_.Root)OSDCloud\Config\Scripts\StartNet2\*.ps1"
148+
Get-ChildItem "$($_.Root)OSDCloud\Config\Scripts\StartNet2\" -Include "*.ps1" -File -Recurse -Force -ErrorAction Ignore
149+
}
150+
if ($Global:ScriptStartNet2) {
151+
$Global:ScriptStartNet2 = $Global:ScriptStartNet2 | Sort-Object -Property FullName
152+
foreach ($Item in $Global:ScriptStartNet2) {
153+
Write-Host -ForegroundColor Gray "Execute $($Item.FullName)"
154+
& "$($Item.FullName)"
155+
}
156+
$TimeSpan = New-TimeSpan -Start $Global:StartnetStart -End (Get-Date)
157+
Write-Host -ForegroundColor DarkGray "$($TimeSpan.ToString("mm':'ss")) Tried to execute Post StartNet Scripts"
158+
}
159+
160+
Write-Host -ForegroundColor Cyan '[i] OSD module update'
161+
$Global:OSDModuleUpdate = $true # Default is trying to newer OSD module
162+
$Global:OSDCloudStartnetJson = Get-PSDrive -PSProvider FileSystem | Where-Object {$_.Name -ne 'C'} | ForEach-Object {
163+
Get-ChildItem "$($_.Root)OSDCloud\Config" -Include "Initialize-OSDCloudStartnet.json" -File -Force -Recurse -ErrorAction Ignore
164+
}
165+
if ($Global:OSDCloudStartnetJson ) {
166+
foreach ($Item in $Global:OSDCloudStartnetJson) {
167+
Write-Host -ForegroundColor DarkGray "$($Item.FullName)"
168+
$Global:OSDModuleUpdate = (Get-Content -Path "$($Item.FullName)" | ConvertFrom-Json -ErrorAction "Stop").OSDAutoUpdate
169+
Write-Host -ForegroundColor DarkGray "- OSDAutoUpdate: $($Global:OSDModuleUpdate)"
158170
}
159171
}
172+
if ($Global:OSDModuleUpdate) {
173+
# Check if the OSD Module in the PowerShell Gallery is newer than the installed version
174+
$TimeSpan = New-TimeSpan -Start $Global:StartnetStart -End (Get-Date)
175+
Write-Host -ForegroundColor DarkGray "$($TimeSpan.ToString("mm':'ss")) Updating OSD PowerShell Module"
176+
$PSModuleName = 'OSD'
177+
$InstalledModule = Get-Module -Name $PSModuleName -ListAvailable -ErrorAction Ignore | Sort-Object Version -Descending | Select-Object -First 1
178+
$GalleryPSModule = Find-Module -Name $PSModuleName -ErrorAction Ignore -WarningAction Ignore
179+
180+
# Install the OSD module if it is not installed or if the version is older than the gallery version
181+
if ($GalleryPSModule) {
182+
if (($GalleryPSModule.Version -as [version]) -gt ($InstalledModule.Version -as [version])) {
183+
Write-Host -ForegroundColor DarkGray "$PSModuleName $($GalleryPSModule.Version) [AllUsers]"
184+
Install-Module $PSModuleName -Scope AllUsers -Force -SkipPublisherCheck
185+
Import-Module $PSModuleName -Force
186+
}
187+
}
188+
} else {
189+
# if json contains {"OSDAutoUpdate": false} then not trying to import newer OSD module
190+
$TimeSpan = New-TimeSpan -Start $Global:StartnetStart -End (Get-Date)
191+
Write-Host -ForegroundColor DarkGray "$($TimeSpan.ToString("mm':'ss")) Skip Updating OSD PowerShell Module"
192+
}
160193
}
161194
}

0 commit comments

Comments
 (0)