зеркало из https://github.com/microsoft/MSLab.git
Коммит
e2dc78e892
|
@ -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
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче