Skip to content

Commit e90de38

Browse files
authored
Merge pull request #272 from P6g9YHK6/main
updates
2 parents f15fca4 + f5557b8 commit e90de38

8 files changed

+527
-34
lines changed
Lines changed: 187 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,187 @@
1+
<#
2+
.SYNOPSIS
3+
This script performs an in-place upgrade of a Windows Server machine by downloading and extracting the ISO file from a specified Nextcloud share.
4+
5+
.DESCRIPTION
6+
The script downloads the ISO from a Nextcloud share, verifies its checksum, extracts it using 7-Zip, and then initiates an in-place upgrade of the server.
7+
The Nextcloud share URL format should be as follows:
8+
https://nextcloud.xxx.xxx/s/xxxxxxxxx/download?path=%2F&files=
9+
All keys are valid for initial installation and from https://learn.microsoft.com/en-us/windows-server/get-started/kms-client-activation-keys?tabs=server2016%2Cwindows1110ltsc%2Cversion1803%2Cwindows81
10+
11+
.EXAMPLE
12+
TARGETED_VERSION=2019
13+
Download_Source=https://nextcloud.xxx.xxx/s/xxxxxxxxx/download?path=%2F&files=
14+
15+
16+
.NOTE
17+
Author: SAN
18+
Date: 14.11.24
19+
#Public
20+
21+
.CHANGELOG
22+
23+
27.03.25 SAN Full code refactorisation for more locale support & checksum verification & transfer repo to a single NC share
24+
25+
.TODO
26+
more testing
27+
find solutions for automated DC server upgrades
28+
Add password on the nextcloud repo and make the script use it
29+
Find a way to use UUP to download the ISO of all windows versions
30+
#>
31+
32+
33+
# Windows Server Versions Metadata
34+
$serverVersions = @{
35+
"2016" = @{
36+
"en" = @{
37+
"file" = "en_windows_server_2016_vl_x64_dvd_11636701.iso"
38+
"checksum" = "47919CE8B4993F531CA1FA3F85941F4A72B47EBAA4D3A321FECF83CA9D17E6B8" # pragma: allowlist-secret
39+
"licenseKey" = "WC2BQ-8NRM3-FDDYY-2BFGV-KHKQY"
40+
}
41+
"fr" = @{
42+
"file" = "fr_windows_server_2016_vl_x64_dvd_11636729.iso"
43+
"checksum" = "81B809A9782C046A48D461AAEBFCD33D07A566C5A990373D0A36CDA1E08EA6F0" # pragma: allowlist-secret
44+
"licenseKey" = "WC2BQ-8NRM3-FDDYY-2BFGV-KHKQY"
45+
}
46+
}
47+
"2019" = @{
48+
"en" = @{
49+
"file" = "en-us_windows_server_2019_x64_dvd_f9475476.iso"
50+
"checksum" = "EA247E5CF4DF3E5829BFAAF45D899933A2A67B1C700A02EE8141287A8520261C" # pragma: allowlist-secret
51+
"licenseKey" = "N69G4-B89J2-4G8F4-WWYCC-J464C"
52+
}
53+
"fr" = @{
54+
"file" = "fr-fr_windows_server_2019_x64_dvd_f6f6acf6.iso"
55+
"checksum" = "E0C6958E94F41163AA1EA9500825B8523136E1B8C5FC03CB7E3900858C7134AD" # pragma: allowlist-secret
56+
"licenseKey" = "N69G4-B89J2-4G8F4-WWYCC-J464C"
57+
}
58+
}
59+
"2022" = @{
60+
"en" = @{
61+
"file" = "en-us_windows_server_2022_updated_nov_2024_x64_dvd_4e34897c.iso"
62+
"checksum" = "0C388FE9D0A524AC603945F5CFFB7CC600A73432BCCCEA3E95274BF851973C96" # pragma: allowlist-secret
63+
"licenseKey" = "VDYBN-27WPP-V4HQT-9VMD4-VMK7H"
64+
}
65+
"fr" = @{
66+
"file" = "fr-fr_windows_server_2022_updated_nov_2024_x64_dvd_4e34897c.iso"
67+
"checksum" = "CCF7FF49503C652E59EE87DE5E66260739F5B20BFB448B3D68411455C291F423" # pragma: allowlist-secret
68+
"licenseKey" = "VDYBN-27WPP-V4HQT-9VMD4-VMK7H"
69+
}
70+
}
71+
"2025" = @{
72+
"en" = @{
73+
"file" = "en-us_windows_server_2025_x64_dvd_b7ec10f3.iso"
74+
"checksum" = "854109E1F215A29FC3541188297A6CA97C8A8F0F8C4DD6236B78DFDF845BF75E" # pragma: allowlist-secret
75+
"licenseKey" = "TVRH6-WHNXV-R9WG3-9XRFY-MY832"
76+
}
77+
"fr" = @{
78+
"file" = "fr-fr_windows_server_2025_x64_dvd_bd6be507.iso"
79+
"checksum" = "45384960A3F430D26454955D1198A6E38E7AA98C9E3906AC1AE9367229C103D0" # pragma: allowlist-secret
80+
"licenseKey" = "TVRH6-WHNXV-R9WG3-9XRFY-MY832"
81+
}
82+
}
83+
}
84+
85+
86+
# Function to compute SHA256 checksum
87+
function Get-FileChecksum {
88+
param ([string]$filePath)
89+
$hashAlgorithm = [System.Security.Cryptography.SHA256]::Create()
90+
$fileStream = [System.IO.File]::OpenRead($filePath)
91+
$checksum = [BitConverter]::ToString($hashAlgorithm.ComputeHash($fileStream)).Replace("-", "").ToUpper()
92+
$fileStream.Close()
93+
return $checksum
94+
}
95+
96+
# Function to verify the checksum of the downloaded file
97+
function Verify-Checksum {
98+
param ([string]$filePath, [string]$expectedChecksum)
99+
if (-not (Test-Path $filePath)) { return $false }
100+
return (Get-FileChecksum -filePath $filePath) -eq $expectedChecksum
101+
}
102+
103+
# Function to perform in-place upgrade
104+
function Perform-InPlaceUpgrade {
105+
param ([string]$setupPath, [string]$licenseKey)
106+
$upgradeArgs = "/auto upgrade /quiet /dynamicupdate disable /imageindex 2 /eula accept /pkey $licenseKey"
107+
Write-Host "Starting in-place upgrade..."
108+
Start-Process -FilePath $setupPath -ArgumentList $upgradeArgs -Wait -NoNewWindow
109+
Write-Host "Upgrade process initiated."
110+
}
111+
112+
# Function to check requirements
113+
function Check-Requirements {
114+
param ([string]$targetedVersion, [string]$baseUrl)
115+
116+
if (-not $targetedVersion) { Write-Host "TARGETED_VERSION is not set. Exiting."; exit 1 }
117+
if (-not $baseUrl) { Write-Host "Download_Source is not set. Exiting."; exit 1 }
118+
119+
# Detect system language (first two letters)
120+
$systemLocale = (Get-WinSystemLocale).Name.Substring(0,2).ToLower()
121+
122+
# Validate language availability
123+
if (-not $serverVersions[$targetedVersion].ContainsKey($systemLocale)) {
124+
Write-Host "Unsupported language: $systemLocale. Exiting."
125+
exit 1
126+
}
127+
128+
# Check for 7-Zip
129+
$sevenZipPath = (Get-Command 7z.exe -ErrorAction SilentlyContinue).Source
130+
if (-not $sevenZipPath) {
131+
$sevenZipPath = "C:\\Program Files\\7-Zip\\7z.exe"
132+
if (-not (Test-Path $sevenZipPath)) {
133+
Write-Host "7-Zip not found in PATH or default location. Exiting."
134+
exit 1
135+
}
136+
}
137+
138+
# Check available disk space
139+
$freeSpace = (Get-PSDrive C).Free
140+
if ($freeSpace -lt 12GB) {
141+
Write-Host "Not enough disk space. Exiting."
142+
exit 1
143+
}
144+
145+
return $systemLocale, $sevenZipPath
146+
}
147+
148+
# Main Execution
149+
$targetedVersion = [Environment]::GetEnvironmentVariable("TARGETED_VERSION")
150+
$baseUrl = $env:Download_Source
151+
152+
# Perform requirements check
153+
$checkResult = Check-Requirements -targetedVersion $targetedVersion -baseUrl $baseUrl
154+
$language = $checkResult[0]
155+
$sevenZipPath = $checkResult[1]
156+
157+
# Fetch metadata
158+
$metadata = $serverVersions[$targetedVersion][$language]
159+
$isoFile = "C:\\Windows\\Temp\\$($metadata.file)"
160+
$extractFolder = "C:\\Windows\\Temp\\windows_server_extract"
161+
162+
# Validate or download ISO
163+
if (!(Verify-Checksum -filePath $isoFile -expectedChecksum $metadata.checksum)) {
164+
Write-Host "Downloading ISO..."
165+
Invoke-WebRequest -Uri "$baseUrl$($metadata.file)" -OutFile $isoFile
166+
if (!(Verify-Checksum -filePath $isoFile -expectedChecksum $metadata.checksum)) {
167+
Write-Host "Checksum verification failed. Exiting."; exit 1
168+
}
169+
}
170+
171+
# Clean and extract ISO
172+
if (Test-Path $extractFolder) { Remove-Item -Recurse -Force $extractFolder }
173+
Write-Host "Extracting ISO..."
174+
Start-Process -FilePath $sevenZipPath -ArgumentList "x `"$isoFile`" -o`"$extractFolder`" -y" -Wait
175+
176+
# Delete ISO file to free up space
177+
Write-Host "Deleting ISO file to free up space..."
178+
Remove-Item -Path $isoFile -Force
179+
180+
# Locate and execute setup.exe
181+
$setupPath = Get-ChildItem -Path $extractFolder -Recurse -Filter "setup.exe" -File | Select-Object -First 1
182+
if ($setupPath) {
183+
Perform-InPlaceUpgrade -setupPath $setupPath.FullName -licenseKey $metadata.licenseKey
184+
} else {
185+
Write-Host "setup.exe not found. Exiting."; exit 1
186+
}
187+

scripts_staging/Checks/Internet uplink.ps1

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,16 +16,17 @@
1616
1717
.NOTES
1818
Author: SAN
19-
Date: ???
19+
Date: 01.01.25
2020
#public
2121
2222
.CHANGELOG
23-
23+
25.03.25 SAN Format output
2424
.TODO
2525
Include customizable input for the list of IP addresses.
2626
Enhance error handling for unreachable hosts.
27-
for test all to env
28-
tnc has some relability issue maybe use normal ping
27+
move test all to env
28+
tnc has some relability issue maybe use normal ping as fallback
29+
2930
#>
3031

3132

@@ -59,10 +60,10 @@ if ($TestAll) {
5960
$pingResult = Test-Connection -ComputerName $ip -Count 1 -Quiet
6061

6162
if (-not $pingResult) {
62-
Write-Host "Ping to $ip ($owner) failed."
63+
Write-Host "KO: Ping to $ip ($owner) failed."
6364
$pingFailed = $true
6465
} else {
65-
Write-Host "Ping to $ip ($owner) succeeded."
66+
Write-Host "OK: Ping to $ip ($owner) succeeded."
6667
}
6768
}
6869

@@ -80,9 +81,9 @@ if ($TestAll) {
8081

8182
# Check the result of the ping and exit with status code 1 if it fails
8283
if (-not $pingResult) {
83-
Write-Host "Ping to $randomIp ($owner) failed."
84+
Write-Host "KO: Ping to $randomIp ($owner) failed."
8485
exit 1
8586
} else {
86-
Write-Host "Ping to $randomIp ($owner) succeeded."
87+
Write-Host "OK: Ping to $randomIp ($owner) succeeded."
8788
}
8889
}

scripts_staging/Checks/SQL Health.ps1

Lines changed: 87 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,24 @@
33
This script performs health checks on a machine with SQL Server installed.
44
55
.DESCRIPTION
6-
The script checks various aspects of SQL Server health, including version and blocked requests.
7-
It provides a modular approach with separate functions for each check.
6+
The script checks various aspects of SQL Server health, including version, blocked requests,
7+
and availability group synchronization. It provides a modular approach with separate functions
8+
for each check.
89
910
.NOTES
1011
Author: SAN
11-
Date: 01.01.24
12+
Date: 01.01.2024
1213
#public
14+
15+
.CHANGELOG
16+
SAN 12.12.2023 Changed outputs
17+
SAN 14.03.2024 Added availability group checks
1318
1419
.TODO
15-
Need to go back to version 1 and implement the missing functions of this check
16-
handle Master-slave monitoring
20+
Optimize query execution
21+
Improve error handling
22+
1723
18-
.CHANGELOG
19-
SAN 12.12.24 Changed outputs
2024
#>
2125

2226
function Get-SqlServerVersion {
@@ -126,13 +130,79 @@ function Get-BlockedSqlRequests {
126130
}
127131

128132
if ($errorEncountered) {
129-
return "Error" # Return "Error" if any error occurred during the process
133+
return "Error"
130134
} else {
131-
return "OK" # Return "OK" if no errors occurred
135+
return "OK"
136+
}
137+
}
138+
139+
Function Get-SqlAgSyncStatus {
140+
Write-Host "Function Get-SqlAgSyncStatus"
141+
142+
$server = "$( $env:COMPUTERNAME)\$( (Get-Item 'HKLM:\Software\Microsoft\Microsoft SQL Server\Instance Names\SQL').Property[0])"
143+
Write-Host "Detected SQL Server Instance: $server"
144+
145+
Function RunQuery($query) {
146+
Try {
147+
$conn = New-Object System.Data.SqlClient.SqlConnection
148+
$conn.ConnectionString = "Server=$server;Database=master;Integrated Security=True"
149+
$conn.Open()
150+
151+
$userQuery = "SELECT SUSER_NAME(), USER_NAME();"
152+
$cmdUser = New-Object System.Data.SqlClient.SqlCommand($userQuery, $conn)
153+
$userReader = $cmdUser.ExecuteReader()
154+
If ($userReader.Read()) {
155+
Write-Host "Connected as: $($userReader.GetString(0)) ($($userReader.GetString(1)))"
156+
}
157+
$userReader.Close()
158+
159+
Write-Host "SQL Connection Successful: $server"
160+
161+
$cmd = New-Object System.Data.SqlClient.SqlCommand($query, $conn)
162+
$adapter = New-Object System.Data.SqlClient.SqlDataAdapter($cmd)
163+
$dataSet = New-Object System.Data.DataSet
164+
$adapter.Fill($dataSet) | Out-Null
165+
$conn.Close()
166+
167+
return $dataSet.Tables[0]
168+
} Catch {
169+
Write-Host "SQL Error: $_"
170+
return $null
171+
}
132172
}
173+
174+
$query = "SELECT c.name, s.synchronization_health FROM sys.availability_groups_cluster c
175+
JOIN sys.dm_hadr_availability_group_states s ON c.group_id = s.group_id
176+
WHERE LOWER(s.primary_replica) = LOWER('$server') OR LOWER('$server') IN
177+
(SELECT LOWER(replica_server_name) FROM sys.availability_replicas);"
178+
179+
$result = RunQuery $query
180+
181+
if ($null -eq $result -or $result.Rows.Count -eq 0) {
182+
Write-Host "OK : $server AG SYNCHRO : No Availability Groups found."
183+
return "OK"
184+
}
185+
186+
Write-Host "Query Result Count: $($result.Rows.Count)"
187+
Write-Host "Query Result: $($result | Out-String)"
188+
189+
$description = ""
190+
$statusLevel = 0
191+
foreach ($row in $result) {
192+
switch ($row.synchronization_health) {
193+
0 { $statusLevel = [Math]::Max($statusLevel, 2); $description += "$($row.name): Not Healthy " }
194+
1 { $statusLevel = [Math]::Max($statusLevel, 1); $description += "$($row.name): Partially Healthy " }
195+
2 { $description += "$($row.name): Healthy " }
196+
}
197+
}
198+
199+
$status = @("OK", "WARNING", "CRITICAL")[$statusLevel]
200+
Write-Host "$status : $server AG SYNCHRO : $description"
201+
return $status
133202
}
134203

135204

205+
136206
function Check-SqlServerInstallation {
137207
# Check if Invoke-Sqlcmd is available
138208
if (Get-Command Invoke-Sqlcmd -ErrorAction SilentlyContinue) {
@@ -150,9 +220,10 @@ if (Check-SqlServerInstallation) {
150220
# Run each function and report the result
151221
$result1 = Get-SqlServerVersion
152222
$result2 = Get-BlockedSqlRequests
223+
$result3 = Get-SqlAgSyncStatus
153224

154225
# Check the results and provide the overall status
155-
if ($result1 -eq "OK" -and $result2 -eq "OK") {
226+
if ($result1 -eq "OK" -and $result2 -eq "OK" -and $result3 -eq "OK") {
156227
Write-Host "OK: All components are functioning properly"
157228
} else {
158229
$errorComponents = @()
@@ -164,9 +235,14 @@ if (Check-SqlServerInstallation) {
164235
if ($result2 -ne "OK") {
165236
$errorComponents += "Blocked SQL Requests Check"
166237
}
238+
239+
if ($result3 -ne "OK") {
240+
$errorComponents += "AG Synchronization Check"
241+
}
167242

168243
$errorList = $errorComponents -join ", "
169244
Write-Host "Overall Status: Some components encountered errors. Errors in: $errorList"
170245
Exit 1
171246
}
172-
}
247+
}
248+

scripts_staging/Checks/Windows Services.ps1

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
28.10.24 SAN - Removed ignored output without the debug flag.
2525
28.10.24 SAN - cleanup documentation.
2626
21.01.25 SAN - Code cleanup
27-
27+
27.03.25 SAN - added kerberos local key to default
2828
2929
#>
3030

@@ -59,7 +59,8 @@ $ignoredByDefault = @(
5959
"CDPSvc",
6060
"AGSService",
6161
"ShellHWDetection", # Frequently failing; unclear if actionable
62-
"DropboxUpdater"
62+
"DropboxUpdater",
63+
"LocalKDC" # https://learn.microsoft.com/en-us/answers/questions/2136070/windows-server-2025-kerberos-local-key-distributio
6364
)
6465

6566
# Check if the "IgnoredServices" environment variable exists and add those services to the ignore list

0 commit comments

Comments
 (0)