Merge pull request #555 from microsoft/dev

Dev
This commit is contained in:
Jaromir Kaspar 2023-06-16 00:31:48 +02:00 коммит произвёл GitHub
Родитель eb02abe7be 2cf38f5dee
Коммит e2dc78e892
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
2 изменённых файлов: 166 добавлений и 117 удалений

Просмотреть файл

@ -171,7 +171,9 @@
}
}
#define and install other features
$features="Failover-Clustering","RSAT-Clustering-PowerShell","Hyper-V-PowerShell","NetworkATC","NetworkHUD","Data-Center-Bridging","RSAT-DataCenterBridging-LLDP-Tools","FS-SMBBW","Bitlocker","RSAT-Feature-Tools-BitLocker","Storage-Replica","RSAT-Storage-Replica","FS-Data-Deduplication","System-Insights","RSAT-System-Insights"
$features="Failover-Clustering","RSAT-Clustering-PowerShell","Hyper-V-PowerShell","NetworkATC","NetworkHUD","Data-Center-Bridging","RSAT-DataCenterBridging-LLDP-Tools","FS-SMBBW"
#optional - affects perf even if not enabled on volumes as filter driver is attached (Bitlocker,SR,Dedup)
#$features+="RSAT-Feature-Tools-BitLocker","Storage-Replica","RSAT-Storage-Replica","FS-Data-Deduplication","System-Insights","RSAT-System-Insights"
Invoke-Command -ComputerName $servers -ScriptBlock {Install-WindowsFeature -Name $using:features}
#endregion
@ -209,7 +211,7 @@
#Configure max evenlope size to be 8kb to be able to copy files using PSSession (useful for dell drivers update region and Windows Admin Center)
Invoke-Command -ComputerName $servers -ScriptBlock {Set-Item -Path WSMan:\localhost\MaxEnvelopeSizekb -Value 8192}
#Configure MaxTimeout (10s for Dell hardware, 30s for Virtual environment https://learn.microsoft.com/en-us/windows-server/storage/storage-spaces/storage-spaces-direct-in-vm)
#Configure MaxTimeout (10s for Dell hardware - especially if you have HDDs, 30s for Virtual environment https://learn.microsoft.com/en-us/windows-server/storage/storage-spaces/storage-spaces-direct-in-vm)
if ((Get-CimInstance -ClassName win32_computersystem -CimSession $servers[0]).Manufacturer -like "*Dell Inc."){
Invoke-Command -ComputerName $servers -ScriptBlock {Set-ItemProperty -Path HKLM:\SYSTEM\CurrentControlSet\Services\spaceport\Parameters -Name HwTimeout -Value 0x00002710}
}
@ -638,7 +640,7 @@
}
#since ATC is not available on management machine, copy PowerShell module over to management machine from cluster. However global intents will not be automatically added as in C:\Windows\System32\WindowsPowerShell\v1.0\Modules\NetworkATC\NetWorkATC.psm1 is being checked if NetATC feature is installed [FabricManager.FeatureStaging]::Feature_NetworkATC_IsEnabled()
$session=New-PSSession -ComputerName $ClusterName
$session=New-PSSession -ComputerName $Servers[0]
$items="C:\Windows\System32\WindowsPowerShell\v1.0\Modules\NetworkATC","C:\Windows\System32\NetworkAtc.Driver.dll","C:\Windows\System32\Newtonsoft.Json.dll","C:\Windows\System32\NetworkAtcFeatureStaging.dll"
foreach ($item in $items){
Copy-Item -FromSession $session -Path $item -Destination $item -Recurse -Force
@ -656,7 +658,7 @@
#grab fastest adapters names (assuming that we are deploying converged intent with just Mellanox or Intel E810)
$FastestLinkSpeed=(get-netadapter -CimSession $Servers | Where-Object {$_.Status -eq "up" -and $_.HardwareInterface -eq $True}).Speed | Sort-Object -Descending | Select-Object -First 1
#grab adapters
$AdapterNames=(Get-NetAdapter -CimSession $ClusterName | Where-Object {$_.Status -eq "up" -and $_.HardwareInterface -eq $True} | where-object Speed -eq $FastestLinkSpeed | Sort-Object Name).Name
$AdapterNames=(Get-NetAdapter -CimSession $Servers[0] | Where-Object {$_.Status -eq "up" -and $_.HardwareInterface -eq $True} | where-object Speed -eq $FastestLinkSpeed | Sort-Object Name).Name
#$AdapterNames="SLOT 3 Port 1","SLOT 3 Port 2"
Import-Module NetworkATC
Add-NetIntent -ClusterName $ClusterName -Name ConvergedIntent -Management -Compute -Storage -AdapterName $AdapterNames -Verbose #-StorageVlans 1,2
@ -751,6 +753,13 @@ if ($NetATC){
Set-NetAdapterAdvancedProperty -CimSession $Servers -InterfaceDescription Mellanox* -DisplayName 'Dcbxmode' -DisplayValue 'Host in charge'
}
}
#configure larger receive buffers on Mellanox adapters
if ((Get-CimInstance -ClassName win32_computersystem -CimSession $servers[0]).Manufacturer -like "*Dell Inc."){
if (Get-NetAdapter -CimSession $Servers -InterfaceDescription Mellanox*){
Set-NetAdapterAdvancedProperty -CimSession $Servers -InterfaceDescription Mellanox* -DisplayName 'Receive buffers' -DisplayValue '4096'
}
}
#endregion
#region Check settings before applying NetATC
@ -1071,7 +1080,9 @@ if ($numberofnodes -eq 16){
Install-Module -Name Az.Resources -Force
}
#choose location for cluster (and RG)
$region=(Get-AzLocation | Where-Object Providers -Contains "Microsoft.AzureStackHCI" | Out-GridView -OutputMode Single -Title "Please select Location for AzureStackHCI metadata").Location
$region=(Get-AzResourceProvider -ProviderNamespace Microsoft.AzureStackHCI).Where{($_.ResourceTypes.ResourceTypeName -eq 'clusters' -and $_.RegistrationState -eq 'Registered')}.Locations | Out-GridView -OutputMode Single -Title "Please select Location for AzureStackHCI metadata"
$region = $region -replace '\s',''
$region = $region.ToLower()
if ($ResourceGroupName){
If (-not (Get-AzResourceGroup -Name $ResourceGroupName -ErrorAction Ignore)){
New-AzResourceGroup -Name $ResourceGroupName -Location $region
@ -1300,7 +1311,7 @@ if ((Get-CimInstance -ClassName win32_computersystem -CimSession $Servers[0]).Ma
#region check if there are any updates are needed
$ScanResult=Invoke-Command -ComputerName $Servers -ScriptBlock {
& "C:\Program Files\Dell\DELL System Update\DSU.exe" --catalog-location="$using:DSUPackageDownloadFolder\ASHCI-Catalog.xml" --preview | Out-Null
& "C:\Program Files\Dell\DELL System Update\DSU.exe" --catalog-location="$env:UserProfile\Downloads\ASHCI-Catalog.xml" --preview | Out-Null
$JSON=Get-content "C:\ProgramData\Dell\DELL System Update\dell_dup\DSU_STATUS.json" | ConvertFrom-JSon
$Result=$JSON.systemupdatestatus.invokerinfo.statusmessage
if ($Result -like "No Applicable Update*" ){
@ -1538,4 +1549,37 @@ if ((Get-CimInstance -ClassName win32_computersystem -CimSession $Servers[0]).Ma
}
$Results | Select-Object "HostName","CurrentIPv4.1.Address","OS-BMC.1.UsbNicIpAddress","IPInsideOS","OS-BMC.1.AdminState"
#endregion
#region reset pool/disks in existing cluster
<#
#disable S2D
Disable-ClusterS2D -CimSession $ClusterName -Confirm:0
#remove cluster disk in SDDC Group
Get-ClusterResource -Cluster $ClusterName | Where-Object OwnerGroup -eq "SDDC Group" | Remove-clusterResource -Force
#remove cluster disk from available storage
Get-ClusterResource -Cluster $ClusterName | Where-Object OwnerGroup -eq "Available Storage" | Remove-clusterResource -Force
#remove Storage Pool from cluster resources
Get-ClusterResource -Cluster $ClusterName | Where-Object resourcetype -eq "Storage Pool" | Remove-ClusterResource -Force
#remove storage pool
Start-Sleep 5
Get-StoragePool -CimSession $ClusterName -FriendlyName S2D* | Set-StoragePool -IsReadOnly $False
Get-StoragePool -FriendlyName S2D* -CimSession $ClusterName | Get-VirtualDisk | Remove-VirtualDisk -Confirm:0
Get-StoragePool -FriendlyName S2D* -CimSession $ClusterName | Remove-StoragePool -Confirm:0
#wipe disks
Invoke-Command -ComputerName $Servers -ScriptBlock {
Get-PhysicalDisk -CanPool $True | Reset-PhysicalDisk
}
Enable-ClusterS2D -CimSession $ClusterName -Confirm:0 -Verbose
#>
#endregion
#region reset health service/performance history
<#
#delete performance history including volume (without invoking it returned error "get-srpartnership : The WS-Management service cannot process the request. The CIM namespace")
Invoke-Command -ComputerName $CLusterName -ScriptBlock {Stop-ClusterPerformanceHistory -DeleteHistory}
#recreate performance history
Start-ClusterPerformanceHistory -CimSession $ClusterName
#>
#endregion
#endregion

Просмотреть файл

@ -17,9 +17,11 @@
#folder on servers where all binaries will be staged
$BinariesLocation="c:\Dell\"
$Offline=$True #assuming nodes are offline. If true, all tools will be downloaded to management machine, all updates will be installed "offline"
$Offline=$false #assuming nodes are offline. If true, all tools will be downloaded to management machine, all updates will be installed "offline"
$MSUpdates="Recommended" #or "All" - for online version only
$MSUpdates="Recommended" #or $false (to skip MS updates) or "All" - for online version only
$DellUpdates=$True #or $False to skip dell updates
$ForceReboot=$false #or $true, to reboot even if there were no updates applied
@ -275,107 +277,108 @@ if ($offline){
#region apply updates on nodes
foreach ($Node in $Nodes){
#Check if reboot is required
if (($Compliance | Where-Object {$_.NodeName -eq $Node -and $_.rebootrequired -eq $True}) -or ($Scanresult | Where-Object ($_.ComputerName -eq $node -and $_.MicrosoftUpdateRequired -eq $True) -or ($ForceReboot -eq $True))){
Write-Output "$(get-date -Format 'yyyy/MM/dd hh:mm:ss tt') $($Node): Reboot is required"
#check for repair jobs, if found, wait until finished
Write-Output "$(get-date -Format 'yyyy/MM/dd hh:mm:ss tt') $($Node): Waiting for Storage jobs to finish"
if ((Get-StorageSubSystem -CimSession $ClusterName -FriendlyName Clus* | Get-StorageJob -CimSession $ClusterName | Where-Object Name -eq Repair) -ne $Null){
do{
$jobs=(Get-StorageSubSystem -CimSession $ClusterName -FriendlyName Clus* | Get-StorageJob -CimSession $ClusterName)
if ($jobs | Where-Object Name -eq Repair){
$count=($jobs | Measure-Object).count
$BytesTotal=($jobs | Measure-Object BytesTotal -Sum).Sum
$BytesProcessed=($jobs | Measure-Object BytesProcessed -Sum).Sum
[System.Console]::Write("$count Repair Storage Job(s) Running. GBytes Processed: $($BytesProcessed/1GB) GBytes Total: $($BytesTotal/1GB) `r")
#Check for Suspended jobs (if there are no running repair jobs, only suspended and still unhealthy disks). Kick the repair with Repair-Virtual disk if so...
if ((($jobs | where-Object Name -eq Repair | where-Object JobState -eq "Running") -eq $Null) -and ($jobs | where-Object Name -eq Repair | where-Object JobState -eq "Suspended") -and (Get-VirtualDisk -CimSession $ClusterName | where healthstatus -ne Healthy)){
Write-Output "Suspended repair job and Degraded virtual disk found. Invoking Virtual Disk repair"
Get-VirtualDisk -CimSession $ClusterName | where-Object HealthStatus -ne "Healthy" | Repair-VirtualDisk
}
Start-Sleep 5
#check for repair jobs, if found, wait until finished
Write-Output "$(get-date -Format 'yyyy/MM/dd hh:mm:ss tt') $($Node): Waiting for Storage jobs to finish"
if ((Get-StorageSubSystem -CimSession $ClusterName -FriendlyName Clus* | Get-StorageJob -CimSession $ClusterName | Where-Object Name -eq Repair) -ne $Null){
do{
$jobs=(Get-StorageSubSystem -CimSession $ClusterName -FriendlyName Clus* | Get-StorageJob -CimSession $ClusterName)
if ($jobs | Where-Object Name -eq Repair){
$count=($jobs | Measure-Object).count
$BytesTotal=($jobs | Measure-Object BytesTotal -Sum).Sum
$BytesProcessed=($jobs | Measure-Object BytesProcessed -Sum).Sum
[System.Console]::Write("$count Repair Storage Job(s) Running. GBytes Processed: $($BytesProcessed/1GB) GBytes Total: $($BytesTotal/1GB) `r")
#Check for Suspended jobs (if there are no running repair jobs, only suspended and still unhealthy disks). Kick the repair with Repair-Virtual disk if so...
if ((($jobs | where-Object Name -eq Repair | where-Object JobState -eq "Running") -eq $Null) -and ($jobs | where-Object Name -eq Repair | where-Object JobState -eq "Suspended") -and (Get-VirtualDisk -CimSession $ClusterName | where healthstatus -ne Healthy)){
Write-Output "Suspended repair job and Degraded virtual disk found. Invoking Virtual Disk repair"
Get-VirtualDisk -CimSession $ClusterName | where-Object HealthStatus -ne "Healthy" | Repair-VirtualDisk
}
}until (($jobs | Where-Object Name -eq Repair) -eq $null)
}
Start-Sleep 5
}
}until (($jobs | Where-Object Name -eq Repair) -eq $null)
}
#Check if all disks are healthy. Wait if not
Write-Output "$(get-date -Format 'yyyy/MM/dd hh:mm:ss tt') $($Node): Checking if all disks are healthy"
if (Get-VirtualDisk -CimSession $ClusterName | Where-Object HealthStatus -ne "Healthy"){
Write-Output "$(get-date -Format 'yyyy/MM/dd hh:mm:ss tt') $($Node): Waiting for virtual disks to become healthy"
do{Start-Sleep 5}while(Get-VirtualDisk -CimSession $ClusterName | Where-Object HealthStatus -ne "Healthy")
}
#Check if all disks are healthy. Wait if not
Write-Output "$(get-date -Format 'yyyy/MM/dd hh:mm:ss tt') $($Node): Checking if all disks are healthy"
if (Get-VirtualDisk -CimSession $ClusterName | Where-Object HealthStatus -ne "Healthy"){
Write-Output "$(get-date -Format 'yyyy/MM/dd hh:mm:ss tt') $($Node): Waiting for virtual disks to become healthy"
do{Start-Sleep 5}while(Get-VirtualDisk -CimSession $ClusterName | Where-Object HealthStatus -ne "Healthy")
}
#Check if all fault domains are healthy. Wait if not
Write-Output "$(get-date -Format 'yyyy/MM/dd hh:mm:ss tt') $($Node): Checking if all fault domains are healthy"
if (Get-StorageFaultDomain -CimSession $ClusterName | Where-Object HealthStatus -ne "Healthy"){
Write-Output "$(get-date -Format 'yyyy/MM/dd hh:mm:ss tt') $($Node): Waiting for fault domains to become healthy"
do{Start-Sleep 5}while(Get-StorageFaultDomain -CimSession $ClusterName | Where-Object HealthStatus -ne "Healthy")
}
#Check if all fault domains are healthy. Wait if not
Write-Output "$(get-date -Format 'yyyy/MM/dd hh:mm:ss tt') $($Node): Checking if all fault domains are healthy"
if (Get-StorageFaultDomain -CimSession $ClusterName | Where-Object HealthStatus -ne "Healthy"){
Write-Output "$(get-date -Format 'yyyy/MM/dd hh:mm:ss tt') $($Node): Waiting for fault domains to become healthy"
do{Start-Sleep 5}while(Get-StorageFaultDomain -CimSession $ClusterName | Where-Object HealthStatus -ne "Healthy")
}
#install microsoft updates (we will do it online to limit when node is suspended)
if ($offline){
Write-Output "$(get-date -Format 'yyyy/MM/dd hh:mm:ss tt') $($Node): Applying offline MSUs"
#apply all MSU from $BinariesLocation
Invoke-Command -ComputerName $Node -ScriptBlock {
$MSUs=Get-ChildItem -Path $using:BinariesLocation\Updates | Where-Object Extension -eq ".msu"
foreach ($MSU in $MSUs) {
Write-Output "$(get-date -Format 'yyyy/MM/dd hh:mm:ss tt') $($using:Node): Applying MSU $($MSU.FullName)"
<#
$CabName="$($MSU.basename -split "_" | Select-Object -First 1).cab"
expand.exe $MSU.FullName $using:BinariesLocation\Updates\ -f:"$CabName" | Out-Null
Add-WindowsPackage -PackagePath "$using:BinariesLocation\Updates\$CabName" -Online | Out-Null
#>
Start-Process -FilePath "$env:systemroot\System32\wusa.exe" -ArgumentList "$($MSU.FullName) /quiet /norestart" -Wait
}
}
}else{
#install Microsoft updates
if (($ScanResult | Where-Object ComputerName -eq $node).MicrosoftUpdateRequired){
Write-Output "$(get-date -Format 'yyyy/MM/dd hh:mm:ss tt') $($Node): Installing $MSUpdates Microsoft Updates online"
#Configure virtual account
Invoke-Command -ComputerName $node -ScriptBlock {
New-PSSessionConfigurationFile -RunAsVirtualAccount -Path $env:TEMP\VirtualAccount.pssc
Register-PSSessionConfiguration -Name 'VirtualAccount' -Path $env:TEMP\VirtualAccount.pssc -Force
} -ErrorAction Ignore
#install update
$MSUpdateInstallResult=Invoke-Command -ComputerName $Node -ConfigurationName 'VirtualAccount' {
$Searcher = New-Object -ComObject Microsoft.Update.Searcher
$SearchResult = $Searcher.Search($using:UpdatesSearchCriteria).Updates
$Session = New-Object -ComObject Microsoft.Update.Session
$Downloader = $Session.CreateUpdateDownloader()
$Downloader.Updates = $SearchResult
$Downloader.Download()
$Installer = New-Object -ComObject Microsoft.Update.Installer
$Installer.Updates = $SearchResult
$Result = $Installer.Install()
$Result
}
#remove temporary virtual account config
Invoke-Command -ComputerName $Node -ScriptBlock {
Unregister-PSSessionConfiguration -Name 'VirtualAccount'
Remove-Item -Path $env:TEMP\VirtualAccount.pssc
}
}else{
Write-Output "$(get-date -Format 'yyyy/MM/dd hh:mm:ss tt') $($Node): Microsoft Updates not required"
$MSUpdateInstallResult=$Null
#install microsoft updates (we will do it online to limit time when node is suspended)
if ($MSUpdates){
if ($offline){
Write-Output "$(get-date -Format 'yyyy/MM/dd hh:mm:ss tt') $($Node): Applying offline MSUs"
#apply all MSU from $BinariesLocation
Invoke-Command -ComputerName $Node -ScriptBlock {
$MSUs=Get-ChildItem -Path $using:BinariesLocation\Updates | Where-Object Extension -eq ".msu"
foreach ($MSU in $MSUs) {
Write-Output "$(get-date -Format 'yyyy/MM/dd hh:mm:ss tt') $($using:Node): Applying MSU $($MSU.FullName)"
<#
$CabName="$($MSU.basename -split "_" | Select-Object -First 1).cab"
expand.exe $MSU.FullName $using:BinariesLocation\Updates\ -f:"$CabName" | Out-Null
Add-WindowsPackage -PackagePath "$using:BinariesLocation\Updates\$CabName" -Online | Out-Null
#>
Start-Process -FilePath "$env:systemroot\System32\wusa.exe" -ArgumentList "$($MSU.FullName) /quiet /norestart" -Wait
}
}
#Suspend node
Write-Output "$(get-date -Format 'yyyy/MM/dd hh:mm:ss tt') $($Node): Suspending Cluster Node"
Suspend-ClusterNode -Name "$Node" -Cluster $ClusterName -Drain -Wait | Out-Null
if (Get-ClusterResource -Cluster $ClusterName | Where-Object OwnerNode -eq $Node | Where-Object State -eq "Online"){
Write-Output "$(get-date -Format 'yyyy/MM/dd hh:mm:ss tt') $($Node): Suspending Cluster Node Failed. Resuming and terminating patch run"
Resume-ClusterNode -Name "$Node" -Cluster $ClusterName -Failback Immediate | Out-Null
break
}else{
#install Microsoft updates
if (($ScanResult | Where-Object ComputerName -eq $node).MicrosoftUpdateRequired){
Write-Output "$(get-date -Format 'yyyy/MM/dd hh:mm:ss tt') $($Node): Installing $MSUpdates Microsoft Updates online"
#Configure virtual account
Invoke-Command -ComputerName $node -ScriptBlock {
New-PSSessionConfigurationFile -RunAsVirtualAccount -Path $env:TEMP\VirtualAccount.pssc
Register-PSSessionConfiguration -Name 'VirtualAccount' -Path $env:TEMP\VirtualAccount.pssc -Force
} -ErrorAction Ignore
#install update
$MSUpdateInstallResult=Invoke-Command -ComputerName $Node -ConfigurationName 'VirtualAccount' {
$Searcher = New-Object -ComObject Microsoft.Update.Searcher
$SearchResult = $Searcher.Search($using:UpdatesSearchCriteria).Updates
$Session = New-Object -ComObject Microsoft.Update.Session
$Downloader = $Session.CreateUpdateDownloader()
$Downloader.Updates = $SearchResult
$Downloader.Download()
$Installer = New-Object -ComObject Microsoft.Update.Installer
$Installer.Updates = $SearchResult
$Result = $Installer.Install()
$Result
}
#remove temporary virtual account config
Invoke-Command -ComputerName $Node -ScriptBlock {
Unregister-PSSessionConfiguration -Name 'VirtualAccount'
Remove-Item -Path $env:TEMP\VirtualAccount.pssc
}
}else{
Write-Output "$(get-date -Format 'yyyy/MM/dd hh:mm:ss tt') $($Node): Microsoft Updates not required"
$MSUpdateInstallResult=$Null
}
}
}
#enable storage maintenance mode
Write-Output "$(get-date -Format 'yyyy/MM/dd hh:mm:ss tt') $($Node): Enabling Storage Maintenance mode"
Get-StorageFaultDomain -CimSession $ClusterName -FriendlyName $Node | Enable-StorageMaintenanceMode -CimSession $ClusterName
#Suspend node
Write-Output "$(get-date -Format 'yyyy/MM/dd hh:mm:ss tt') $($Node): Suspending Cluster Node"
Suspend-ClusterNode -Name "$Node" -Cluster $ClusterName -Drain -Wait | Out-Null
#Install Dell updates https://dl.dell.com/content/manual36290092-dell-emc-system-update-version-1-9-3-0-user-s-guide.pdf?language=en-us&ps=true
if (Get-ClusterResource -Cluster $ClusterName | Where-Object OwnerNode -eq $Node | Where-Object State -eq "Online"){
Write-Output "$(get-date -Format 'yyyy/MM/dd hh:mm:ss tt') $($Node): Suspending Cluster Node Failed. Resuming and terminating patch run"
Resume-ClusterNode -Name "$Node" -Cluster $ClusterName -Failback Immediate | Out-Null
break
}
#enable storage maintenance mode
Write-Output "$(get-date -Format 'yyyy/MM/dd hh:mm:ss tt') $($Node): Enabling Storage Maintenance mode"
Get-StorageFaultDomain -CimSession $ClusterName -FriendlyName $Node | Enable-StorageMaintenanceMode -CimSession $ClusterName
#Install Dell updates https://dl.dell.com/content/manual36290092-dell-emc-system-update-version-1-9-3-0-user-s-guide.pdf?language=en-us&ps=true
#assuming dell updates might interrupt server, therefore it's done during maintenance mode
if ($DellUpdates){
$UpdateNames=(($Compliance | Where-Object {$_.NodeName -eq $Node -and $_.compliancestatus -eq $false}).PackageFilePath | Split-Path -Leaf) -join ","
if ($UpdateNames){
if ($offline){
@ -390,32 +393,34 @@ if ($offline){
}
}
}
}
#Check if reboot is required and reboot
if (($Compliance | Where-Object {$_.NodeName -eq $Node -and $_.rebootrequired -eq $True}) -or ($Scanresult | Where-Object ($_.ComputerName -eq $node -and $_.MicrosoftUpdateRequired -eq $True) -or ($ForceReboot -eq $True))){
Write-Output "$(get-date -Format 'yyyy/MM/dd hh:mm:ss tt') $($Node): Reboot is required"
#restart node and wait for PowerShell to come up (with powershell 7 you need to wait for WINRM :)
Write-Output "$(get-date -Format 'yyyy/MM/dd hh:mm:ss tt') $($Node): Restarting Cluster Node"
Restart-Computer -ComputerName $Node -Protocol WSMan -Wait -For PowerShell | Out-Null
#disable storage maintenance mode
Write-Output "$(get-date -Format 'yyyy/MM/dd hh:mm:ss tt') $($Node): Disabling Storage Maintenance mode"
Get-StorageFaultDomain -Type StorageScaleUnit -CimSession $Node | Where-Object FriendlyName -eq $Node | Disable-StorageMaintenanceMode -CimSession $Node
#resume cluster node
Write-Output "$(get-date -Format 'yyyy/MM/dd hh:mm:ss tt') $($Node): Resuming Cluster Node"
Resume-ClusterNode -Name "$Node" -Cluster $ClusterName -Failback Immediate | Out-Null
#wait for machines to finish live migration
Write-Output "$(get-date -Format 'yyyy/MM/dd hh:mm:ss tt') $($Node): Waiting for Live migrations to finish"
do {Start-Sleep 5}while(
Get-CimInstance -CimSession $Nodes -Namespace root\virtualization\v2 -ClassName Msvm_MigrationJob | Where-Object StatusDescriptions -eq "Job is running"
)
}else{
Write-Output "$(get-date -Format 'yyyy/MM/dd hh:mm:ss tt') $($Node): Reboot is not required"
}
#disable storage maintenance mode
Write-Output "$(get-date -Format 'yyyy/MM/dd hh:mm:ss tt') $($Node): Disabling Storage Maintenance mode"
Get-StorageFaultDomain -Type StorageScaleUnit -CimSession $Node | Where-Object FriendlyName -eq $Node | Disable-StorageMaintenanceMode -CimSession $Node
#resume cluster node
Write-Output "$(get-date -Format 'yyyy/MM/dd hh:mm:ss tt') $($Node): Resuming Cluster Node"
Resume-ClusterNode -Name "$Node" -Cluster $ClusterName -Failback Immediate | Out-Null
#wait for machines to finish live migration
Write-Output "$(get-date -Format 'yyyy/MM/dd hh:mm:ss tt') $($Node): Waiting for Live migrations to finish"
do {Start-Sleep 5}while(
Get-CimInstance -CimSession $Nodes -Namespace root\virtualization\v2 -ClassName Msvm_MigrationJob | Where-Object StatusDescriptions -eq "Job is running"
)
}
#cleanup updates folder on nodes
Invoke-Command -ComputerName $Nodes -ScriptBlock {
Remove-Item -Path $using:BinariesLocation\Updates -Recurse -Force
Remove-Item -Path $using:BinariesLocation\Updates -Recurse -Force -ErrorAction Ignore
}
#endregion