diff --git a/Scenarios/AzSHCI Deployment 22H2 Edition/Scenario.ps1 b/Scenarios/AzSHCI Deployment 22H2 Edition/Scenario.ps1 index eab3afbc..628b2ec2 100644 --- a/Scenarios/AzSHCI Deployment 22H2 Edition/Scenario.ps1 +++ b/Scenarios/AzSHCI Deployment 22H2 Edition/Scenario.ps1 @@ -16,6 +16,25 @@ #Distributed Cluster ManagementPoint? (Cluster Name in DNS will have IP of every node - like SOFS). If $ClusterIP is set, then $clusterIP will be ignored). $DistributedManagementPoint=$false + #Deploy network using Network ATC? + $NetATC=$False + + #Variables for traditional networking (no NetATC) + $vSwitchName="vSwitch" + #start IP for Storage networks + $IP=1 + #storage networks + $StorNet1="172.16.1." + $StorNet2="172.16.2." + $StorVLAN1=1 + $StorVLAN2=2 + #Jumbo Frames? Might be necessary to increase for iWARP. If not default, make sure all switches are configured end-to-end and (for example 9216). Also if non-default is set, you might run into various issues such as https://blog.workinghardinit.work/2019/09/05/fixing-slow-roce-rdma-performance-with-winof-2-to-winof/. + #if 1514 is set, setting JumboFrames is skipped. All NICs are configured (vNICs + pNICs) + $JumboSize=1514 #9014, 4088 or 1514 (default) + #DCB for ROCE RDMA? + $RoCE=$True + $iWARP=$False + #Perform Windows update? (for more info visit WU Scenario https://github.com/microsoft/WSLab/tree/dev/Scenarios/Windows%20Update) $WindowsUpdate="Recommended" #Can be "All","Recommended" or "None" @@ -187,18 +206,10 @@ 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} } - if ((Get-CimInstance -ClassName win32_computersystem -CimSession $ClusterName).Model -eq "Virtual Machine"){ + if ((Get-CimInstance -ClassName win32_computersystem -CimSession $servers[0]).Model -eq "Virtual Machine"){ Invoke-Command -ComputerName $servers -ScriptBlock {Set-ItemProperty -Path HKLM:\SYSTEM\CurrentControlSet\Services\spaceport\Parameters -Name HwTimeout -Value 0x00007530} } - #Configure dcbxmode to be host in charge (default is firmware in charge) on mellanox adapters (Dell recommendation) - #Caution: This disconnects 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 'Dcbxmode' -DisplayValue 'Host in charge' - } - } - #endregion #region configure OS Security (tbd: https://aka.ms/hci-securitybase) @@ -305,7 +316,7 @@ $Sessions | Remove-PSSession #endregion - + #region check if there are any updates 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 @@ -355,7 +366,9 @@ #install DSU updates Start-Process -FilePath "install.cmd" -Wait -WorkingDirectory $using:DSUPackageDownloadFolder #display result - Get-Content "C:\ProgramData\Dell\DELL System Update\dell_dup\DSU_STATUS.json" + $json=Get-Content "C:\ProgramData\Dell\DELL System Update\dell_dup\DSU_STATUS.json" | ConvertFrom-Json + $output=$json.SystemUpdateStatus.updateablecomponent | Select-Object Name,Version,Baselineversion,UpdateStatus,RebootRequired + Return $output } }else{ Write-Output "$($Server): Dell System Updates not required" @@ -374,6 +387,134 @@ } #endregion +#region configure network (traditional, not NetATC) (best practices are covered in this guide http://aka.ms/ConvergedRDMA ). For more information about networking you can look at this scenario: https://github.com/microsoft/WSLab/tree/master/Scenarios/S2D%20and%20Networks%20deep%20dive + if (-not($NetATC)){ + #Disable unused (disconnected) adapters + Get-Netadapter -CimSession $Servers | Where-Object Status -ne "Up" | Disable-NetAdapter -Confirm:0 + + #Create vSwitch and use the fastest NICs in the server (SR-IOV enabled). Grabs fastest unique NIC + Invoke-Command -ComputerName $servers -ScriptBlock { + $FastestLinkSpeed=(get-netadapter | Where-Object Status -eq Up).Speed| Sort-Object -Descending | Select-Object -First 1 + $NetAdapters=Get-NetAdapter | Where-Object Status -eq Up | Where-Object Speed -eq $FastestLinkSpeed | Sort-Object Name + New-VMSwitch -Name $using:vSwitchName -EnableEmbeddedTeaming $TRUE -EnableIov $true -NetAdapterName $NetAdapters.Name + } + + #add vNICs + foreach ($Server in $Servers){ + #rename Management vNIC first + Rename-VMNetworkAdapter -ManagementOS -Name $vSwitchName -NewName Management -ComputerName $Server + #add SMB vNICs (number depends on how many NICs are connected to vSwitch) + $SMBvNICsCount=(Get-VMSwitch -CimSession $Server -Name $vSwitchName).NetAdapterInterfaceDescriptions.Count + foreach ($number in (1..$SMBvNICsCount)){ + $TwoDigitNumber="{0:D2}" -f $Number + Add-VMNetworkAdapter -ManagementOS -Name "SMB$TwoDigitNumber" -SwitchName $vSwitchName -CimSession $Server + } + + #configure IP Addresses + foreach ($number in (1..$SMBvNICsCount)){ + $TwoDigitNumber="{0:D2}" -f $Number + if ($number % 2 -eq 1){ + New-NetIPAddress -IPAddress ($StorNet1+$IP.ToString()) -InterfaceAlias "vEthernet (SMB$TwoDigitNumber)" -CimSession $Server -PrefixLength 24 + }else{ + New-NetIPAddress -IPAddress ($StorNet2+$IP.ToString()) -InterfaceAlias "vEthernet (SMB$TwoDigitNumber)" -CimSession $Server -PrefixLength 24 + $IP++ + } + } + } + + Start-Sleep 5 + Clear-DnsClientCache + + #Configure the host vNIC to use a Vlan. They can be on the same or different VLans + If ($NumberOfStorageNets -eq 1){ + Set-VMNetworkAdapterVlan -VMNetworkAdapterName SMB* -VlanId $StorVLAN -Access -ManagementOS -CimSession $Servers + }else{ + #configure Odds and Evens for VLAN1 and VLAN2 + foreach ($Server in $Servers){ + $NetAdapters=Get-VMNetworkAdapter -CimSession $server -ManagementOS -Name *SMB* | Sort-Object Name + $i=1 + foreach ($NetAdapter in $NetAdapters){ + if (($i % 2) -eq 1){ + Set-VMNetworkAdapterVlan -VMNetworkAdapterName $NetAdapter.Name -VlanId $StorVLAN1 -Access -ManagementOS -CimSession $Server + $i++ + }else{ + Set-VMNetworkAdapterVlan -VMNetworkAdapterName $NetAdapter.Name -VlanId $StorVLAN2 -Access -ManagementOS -CimSession $Server + $i++ + } + } + } + } + + #Restart each host vNIC adapter so that the Vlan is active. + Get-NetAdapter -CimSession $Servers -Name "vEthernet (SMB*)" | Restart-NetAdapter + + #Enable RDMA on the host vNIC adapters + Enable-NetAdapterRDMA -Name "vEthernet (SMB*)" -CimSession $Servers + + #Associate each of the vNICs configured for RDMA to a physical adapter that is up and is not virtual (to be sure that each RDMA enabled ManagementOS vNIC is mapped to separate RDMA pNIC) + Invoke-Command -ComputerName $servers -ScriptBlock { + #grab adapter names + $physicaladapternames=(get-vmswitch $using:vSwitchName).NetAdapterInterfaceDescriptions + #map pNIC and vNICs + $vmNetAdapters=Get-VMNetworkAdapter -Name "SMB*" -ManagementOS + $i=0 + foreach ($vmNetAdapter in $vmNetAdapters){ + $TwoDigitNumber="{0:D2}" -f ($i+1) + Set-VMNetworkAdapterTeamMapping -VMNetworkAdapterName "SMB$TwoDigitNumber" -ManagementOS -PhysicalNetAdapterName (get-netadapter -InterfaceDescription $physicaladapternames[$i]).name + $i++ + } + } + + #Configure Jumbo Frames + if ($JumboSize -ne 1514){ + Set-NetAdapterAdvancedProperty -CimSession $Servers -DisplayName "Jumbo Packet" -RegistryValue $JumboSize + } + + #Configure dcbxmode to be host in charge (default is firmware in charge) on mellanox adapters (Dell recommendation) + if (Get-NetAdapter -CimSession $Servers -InterfaceDescription Mellanox*){ + Set-NetAdapterAdvancedProperty -CimSession $Servers -InterfaceDescription Mellanox* -DisplayName 'Dcbxmode' -DisplayValue 'Host in charge' + } + + + #configure DCB if requested + if ($ROCE -eq $True){ + #Install DCB + foreach ($server in $servers) {Install-WindowsFeature -Name "Data-Center-Bridging" -ComputerName $server} + ##Configure QoS + New-NetQosPolicy "SMB" -NetDirectPortMatchCondition 445 -PriorityValue8021Action 3 -CimSession $servers + New-NetQosPolicy "ClusterHB" -Cluster -PriorityValue8021Action 7 -CimSession $servers + New-NetQosPolicy "Default" -Default -PriorityValue8021Action 0 -CimSession $servers + + #Turn on Flow Control for SMB + Invoke-Command -ComputerName $servers -ScriptBlock {Enable-NetQosFlowControl -Priority 3} + + #Disable flow control for other traffic than 3 (pause frames should go only from prio 3) + Invoke-Command -ComputerName $servers -ScriptBlock {Disable-NetQosFlowControl -Priority 0,1,2,4,5,6,7} + + #Disable Data Center bridging exchange (disable accept data center bridging (DCB) configurations from a remote device via the DCBX protocol, which is specified in the IEEE data center bridging (DCB) standard.) + Invoke-Command -ComputerName $servers -ScriptBlock {Set-NetQosDcbxSetting -willing $false -confirm:$false} + + #Configure IeeePriorityTag + #IeePriorityTag needs to be On if you want tag your nonRDMA traffic for QoS. Can be off if you use adapters that pass vSwitch (both SR-IOV and RDMA bypasses vSwitch) + Invoke-Command -ComputerName $servers -ScriptBlock {Set-VMNetworkAdapter -ManagementOS -Name "SMB*" -IeeePriorityTag on} + + #Apply policy to the target adapters. The target adapters are adapters connected to vSwitch + Invoke-Command -ComputerName $servers -ScriptBlock {Enable-NetAdapterQos -InterfaceDescription (Get-VMSwitch).NetAdapterInterfaceDescriptions} + + #Create a Traffic class and give SMB Direct 50% of the bandwidth minimum. The name of the class will be "SMB". + #This value needs to match physical switch configuration. Value might vary based on your needs. + #If connected directly (in 2 node configuration) skip this step. + Invoke-Command -ComputerName $servers -ScriptBlock {New-NetQosTrafficClass "SMB" -Priority 3 -BandwidthPercentage 50 -Algorithm ETS} + Invoke-Command -ComputerName $servers -ScriptBlock {New-NetQosTrafficClass "ClusterHB" -Priority 7 -BandwidthPercentage 1 -Algorithm ETS} + } + + #enable iWARP firewall rule if requested + if ($iWARP -eq $True){ + Enable-NetFirewallRule -Name "FPSSMBD-iWARP-In-TCP" -CimSession $servers + } + } +#endregion + #region Create cluster #Create Cluster if ((Get-CimInstance -ClassName win32_computersystem -CimSession $Servers[0]).Manufacturer -like "*Dell*"){ @@ -428,12 +569,40 @@ } #endregion +#region configure cluster networking (not NetATC) + if (-not($NetATC)){ + #rename networks + (Get-ClusterNetwork -Cluster $clustername | Where-Object Address -eq $StorNet1"0").Name="SMB01" + (Get-ClusterNetwork -Cluster $clustername | Where-Object Address -eq $StorNet2"0").Name="SMB02" + #Rename Management Network + (Get-ClusterNetwork -Cluster $clustername | Where-Object Role -eq "ClusterAndClient").Name="Management" + #Rename and Configure USB NICs + if ((Get-CimInstance -ClassName win32_computersystem -CimSession $Servers[0]).Manufacturer -like "*Dell Inc."){ + $Network=(Get-ClusterNetworkInterface -Cluster $ClusterName | Where-Object Adapter -eq "Remote NDIS Compatible Device").Network | Select-Object -Unique + $Network.Name="iDRAC" + $Network.Role="none" + } + #configure Live Migration network + Get-ClusterResourceType -Cluster $clustername -Name "Virtual Machine" | Set-ClusterParameter -Name MigrationExcludeNetworks -Value ([String]::Join(";",(Get-ClusterNetwork -Cluster $clustername | Where-Object {$_.Role -ne "Cluster"}).ID)) + #Configure Live Migration Performance option + Set-VMHost -VirtualMachineMigrationPerformanceOption SMB -cimsession $servers + #Configure number of Live migrations + + #Configure SMB Bandwidth Limits for Live Migration https://techcommunity.microsoft.com/t5/Failover-Clustering/Optimizing-Hyper-V-Live-Migrations-on-an-Hyperconverged/ba-p/396609 + #install feature + Invoke-Command -ComputerName $servers -ScriptBlock {Install-WindowsFeature -Name "FS-SMBBW"} + #Calculate 40% of capacity of NICs in vSwitch (considering 2 NICs, if 1 fails, it will not consume all bandwith, therefore 40%) + $Adapters=(Get-VMSwitch -CimSession $Servers[0]).NetAdapterInterfaceDescriptions + $BytesPerSecond=((Get-NetAdapter -CimSession $Servers[0] -InterfaceDescription $adapters).TransmitLinkSpeed | Measure-Object -Sum).Sum/8 + Set-SmbBandwidthLimit -Category LiveMigration -BytesPerSecond ($BytesPerSecond*0.4) -CimSession $Servers + } +#endregion + #region configure Cluster-Aware-Updating if ($CAURoleName){ #Install required features on nodes. - $ClusterNodes=(Get-ClusterNode -Cluster $ClusterName).Name - foreach ($ClusterNode in $ClusterNodes){ - Install-WindowsFeature -Name RSAT-Clustering-PowerShell -ComputerName $ClusterNode + Invoke-Command -ComputerName $Servers -ScriptBlock { + Install-WindowsFeature -Name RSAT-Clustering-PowerShell } #add role Add-CauClusterRole -ClusterName $ClusterName -MaxFailedNodes 0 -RequireAllNodesOnline -EnableFirewallRules -VirtualComputerObjectName $CAURoleName -Force -CauPluginName Microsoft.WindowsUpdatePlugin -MaxRetriesPerNode 3 -CauPluginArguments @{ 'IncludeRecommendedUpdates' = 'False' } -StartDate "3/2/2017 3:00:00 AM" -DaysOfWeek 4 -WeeksOfMonth @(3) -verbose @@ -443,137 +612,159 @@ #endregion #region Configure networking with NetATC https://techcommunity.microsoft.com/t5/networking-blog/network-atc-what-s-coming-in-azure-stack-hci-22h2/ba-p/3598442 - #make sure NetATC and other required features are installed on servers - Invoke-Command -ComputerName $Servers -ScriptBlock { - Install-WindowsFeature -Name NetworkATC,Data-Center-Bridging,RSAT-Clustering-PowerShell,RSAT-Hyper-V-Tools - } - - #netatc CredSSP (hopefully CredSSP and "-ClusterName LocalHost" will go away in 11c) - # Temporarily enable CredSSP delegation to avoid double-hop issue - $CredSSPUserName="corp\LabAdmin" - $CredSSPPassword="LS1setup!" - foreach ($Server in $Servers){ - Enable-WSManCredSSP -Role "Client" -DelegateComputer $Server -Force + if ($NetATC){ + #make sure NetATC and other required features are installed on servers + Invoke-Command -ComputerName $Servers -ScriptBlock { + Install-WindowsFeature -Name NetworkATC,Data-Center-Bridging,RSAT-Clustering-PowerShell,RSAT-Hyper-V-Tools } - Invoke-Command -ComputerName $Servers -ScriptBlock { Enable-WSManCredSSP Server -Force } - - $SecureStringPassword = ConvertTo-SecureString $CredSSPPassword -AsPlainText -Force - $Credentials = New-Object System.Management.Automation.PSCredential ($CredSSPUserName, $SecureStringPassword) - - if ((Get-CimInstance -ClassName win32_computersystem -CimSession $servers[0]).Model -eq "Virtual Machine"){ - Invoke-Command -ComputerName $servers[0] -Credential $Credentials -Authentication Credssp -ScriptBlock { - Import-Module NetworkATC - #virtual environment (skipping RDMA config) - $AdapterOverride = New-NetIntentAdapterPropertyOverrides - $AdapterOverride.NetworkDirect = 0 - Add-NetIntent -ClusterName LocalHost -Name ConvergedIntent -Management -Compute -Storage -AdapterName "Ethernet","Ethernet 2" -AdapterPropertyOverrides $AdapterOverride -Verbose #-StorageVlans 1,2 + + #netatc CredSSP (hopefully CredSSP and "-ClusterName LocalHost" will go away in 11c) + # Temporarily enable CredSSP delegation to avoid double-hop issue + $CredSSPUserName="corp\LabAdmin" + $CredSSPPassword="LS1setup!" + foreach ($Server in $Servers){ + Enable-WSManCredSSP -Role "Client" -DelegateComputer $Server -Force } - }else{ - #real hardware - #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="SLOT 3 Port 1","SLOT 3 Port 2" - Invoke-Command -ComputerName $servers[0] -Credential $Credentials -Authentication Credssp -ScriptBlock { - Import-Module NetworkATC - Add-NetIntent -ClusterName LocalHost -Name ConvergedIntent -Management -Compute -Storage -AdapterName $using:AdapterNames -Verbose #-StorageVlans 1,2 + Invoke-Command -ComputerName $Servers -ScriptBlock { Enable-WSManCredSSP Server -Force } + + $SecureStringPassword = ConvertTo-SecureString $CredSSPPassword -AsPlainText -Force + $Credentials = New-Object System.Management.Automation.PSCredential ($CredSSPUserName, $SecureStringPassword) + + if ((Get-CimInstance -ClassName win32_computersystem -CimSession $servers[0]).Model -eq "Virtual Machine"){ + Invoke-Command -ComputerName $servers[0] -Credential $Credentials -Authentication Credssp -ScriptBlock { + Import-Module NetworkATC + #virtual environment (skipping RDMA config) + $AdapterOverride = New-NetIntentAdapterPropertyOverrides + $AdapterOverride.NetworkDirect = 0 + Add-NetIntent -ClusterName LocalHost -Name ConvergedIntent -Management -Compute -Storage -AdapterName "Ethernet","Ethernet 2" -AdapterPropertyOverrides $AdapterOverride -Verbose #-StorageVlans 1,2 + } + }else{ + #real hardware + #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="SLOT 3 Port 1","SLOT 3 Port 2" + Invoke-Command -ComputerName $servers[0] -Credential $Credentials -Authentication Credssp -ScriptBlock { + Import-Module NetworkATC + Add-NetIntent -ClusterName LocalHost -Name ConvergedIntent -Management -Compute -Storage -AdapterName $using:AdapterNames -Verbose #-StorageVlans 1,2 + } } - } - #check - Start-Sleep 20 #let intent propagate a bit - Write-Output "applying intent" - do { - $status=Invoke-Command -ComputerName $servers[0] -ScriptBlock {Get-NetIntentStatus -ClusterName LocalHost} - Write-Host "." -NoNewline - Start-Sleep 5 - } while ($status.ConfigurationStatus -contains "Provisioning" -or $status.ConfigurationStatus -contains "Retrying") - - #remove if necessary - <# - Invoke-Command -ComputerName $servers[0] -ScriptBlock { - $intents = Get-NetIntent -ClusterName localhost - foreach ($intent in $intents){ - Remove-NetIntent -Name $intent.IntentName -ClusterName Localhost + #check + Start-Sleep 20 #let intent propagate a bit + Write-Output "applying intent" + do { + $status=Invoke-Command -ComputerName $servers[0] -ScriptBlock {Get-NetIntentStatus -ClusterName LocalHost} + Write-Host "." -NoNewline + Start-Sleep 5 + } while ($status.ConfigurationStatus -contains "Provisioning" -or $status.ConfigurationStatus -contains "Retrying") + + #remove if necessary + <# + Invoke-Command -ComputerName $servers[0] -ScriptBlock { + $intents = Get-NetIntent -ClusterName localhost + foreach ($intent in $intents){ + Remove-NetIntent -Name $intent.IntentName -ClusterName Localhost + } } - } - #> + #> - #if deploying in VMs, some nodes might fail (quarantined state) and even CNO can go to offline ... go to cluadmin and fix - #Get-ClusterNode -Cluster $ClusterName | Where-Object State -eq down | Start-ClusterNode -ClearQuarantine + #if deploying in VMs, some nodes might fail (quarantined state) and even CNO can go to offline ... go to cluadmin and fix + #Get-ClusterNode -Cluster $ClusterName | Where-Object State -eq down | Start-ClusterNode -ClearQuarantine - # Disable CredSSP - Disable-WSManCredSSP -Role Client - Invoke-Command -ComputerName $servers -ScriptBlock { Disable-WSManCredSSP Server } + # Disable CredSSP + Disable-WSManCredSSP -Role Client + Invoke-Command -ComputerName $servers -ScriptBlock { Disable-WSManCredSSP Server } - <# - #since ATC is not available on managment machine, you can copy PowerShell module over. However not everything works as in C:\Windows\System32\WindowsPowerShell\v1.0\Modules\NetworkATC\NetWorkATC.psm1 is often being checked if NetATC feature is installed [FabricManager.FeatureStaging]::Feature_NetworkATC_IsEnabled() - $session=New-PSSession -ComputerName $ClusterName - $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 - } - #> + <# + #since ATC is not available on managment machine, you can copy PowerShell module over. However not everything works as in C:\Windows\System32\WindowsPowerShell\v1.0\Modules\NetworkATC\NetWorkATC.psm1 is often being checked if NetATC feature is installed [FabricManager.FeatureStaging]::Feature_NetworkATC_IsEnabled() + $session=New-PSSession -ComputerName $ClusterName + $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 + } + #> + } +#endregion +#region install network HUD (NetATC) +if ($NetATC){ + #make sure NetworkHUD feature is installed and started on servers + Invoke-Command -ComputerName $Servers -ScriptBlock { + Install-WindowsFeature -Name "NetworkHUD" + Set-Service -Name NetworkHUD -StartupType Automatic + Start-Service -Name NetworkHUD + } +} #endregion #region configure what was/was not configured with NetATC - #disable unused adapters - Get-Netadapter -CimSession $Servers | Where-Object Status -ne "Up" | Disable-NetAdapter -Confirm:0 + if ($NetATC){ + #disable unused adapters + Get-Netadapter -CimSession $Servers | Where-Object Status -ne "Up" | Disable-NetAdapter -Confirm:0 + + #Rename and Configure USB NICs (iDRAC Network) + $USBNics=get-netadapter -CimSession $Servers -InterfaceDescription "Remote NDIS Compatible Device" -ErrorAction Ignore + if ($USBNics){ + $Network=(Get-ClusterNetworkInterface -Cluster $ClusterName | Where-Object Adapter -eq "Remote NDIS Compatible Device").Network | Select-Object -Unique + $Network.Name="iDRAC" + $Network.Role="none" + } - #Rename and Configure USB NICs (iDRAC Network) - $USBNics=get-netadapter -CimSession $Servers -InterfaceDescription "Remote NDIS Compatible Device" -ErrorAction Ignore - if ($USBNics){ - $Network=(Get-ClusterNetworkInterface -Cluster $ClusterName | Where-Object Adapter -eq "Remote NDIS Compatible Device").Network | Select-Object -Unique - $Network.Name="iDRAC" - $Network.Role="none" - } + #Check what networks were excluded from Live Migration + $Networks=(Get-ClusterResourceType -Cluster $clustername -Name "Virtual Machine" | Get-ClusterParameter -Name MigrationExcludeNetworks).Value -split ";" + foreach ($Network in $Networks){Get-ClusterNetwork -Cluster $ClusterName | Where-Object ID -Match $Network} - #Check what networks were excluded from Live Migration - $Networks=(Get-ClusterResourceType -Cluster $clustername -Name "Virtual Machine" | Get-ClusterParameter -Name MigrationExcludeNetworks).Value -split ";" - foreach ($Network in $Networks){Get-ClusterNetwork -Cluster $ClusterName | Where-Object ID -Match $Network} + #check Live Migration option + Get-VMHost -CimSession $Servers | Select-Object *Migration* - #check Live Migration option - Get-VMHost -CimSession $Servers | Select-Object *Migration* + #Check LiveMigrationPerf option and Limit + Get-Cluster -Name $ClusterName | Select-Object *SMB* - #Check LiveMigrationPerf option and Limit - Get-Cluster -Name $ClusterName | Select-Object *SMB* + #check VLAN settings + Get-VMNetworkAdapterIsolation -CimSession $Servers -ManagementOS - #check VLAN settings - Get-VMNetworkAdapterIsolation -CimSession $Servers -ManagementOS + #adjust if necessary (Global cluster overrides may/may not work as there is a bug in 22h2 importing this piece of powershell module - [FabricManager.FeatureStaging]::Feature_NetworkATC_IsEnabled() sometimes work, sometimes not. Need to explore more) + Invoke-Command -ComputerName $Servers[0] -ScriptBlock { + $overrides=New-NetIntentGlobalClusterOverrides + $overrides.MaximumVirtualMachineMigrations=4 + $overrides.MaximumSMBMigrationBandwidthInGbps=20 + $overrides.VirtualMachineMigrationPerformanceOption="SMB" + Set-NetIntent -ClusterName LocalHost -GlobalClusterOverrides $overrides + } - #adjust if necessary - Invoke-Command -ComputerName $Servers[0] -ScriptBlock { - $overrides=New-NetIntentGlobalClusterOverrides - $overrides.MaximumVirtualMachineMigrations=4 - $overrides.MaximumSMBMigrationBandwidthInGbps=20 - $overrides.VirtualMachineMigrationPerformanceOption="SMB" - Set-NetIntent -ClusterName LocalHost -GlobalClusterOverrides $overrides - } + Start-Sleep 20 #let intent propagate a bit + Write-Output "applying overrides intent" + do { + $status=Invoke-Command -ComputerName $Servers[0] -ScriptBlock {Get-NetIntentStatus -Globaloverrides -ClusterName LocalHost} + Write-Host "." -NoNewline + Start-Sleep 5 + } while ($status.ConfigurationStatus -contains "Provisioning" -or $status.ConfigurationStatus -contains "Retrying") - Start-Sleep 20 #let intent propagate a bit - Write-Output "applying overrides intent" - do { - $status=Invoke-Command -ComputerName $Servers[0] -ScriptBlock {Get-NetIntentStatus -Globaloverrides -ClusterName LocalHost} - Write-Host "." -NoNewline - Start-Sleep 5 - } while ($status.ConfigurationStatus -contains "Provisioning" -or $status.ConfigurationStatus -contains "Retrying") + #check Live Migration option + Get-VMHost -CimSession $Servers | Select-Object *Migration* - #check Live Migration option - Get-VMHost -CimSession $Servers | Select-Object *Migration* + #Check LiveMigrationPerf option and Limit (Need more research on how the bandwidth works as it seems unchanged) + Get-Cluster -Name $ClusterName | Select-Object *SMB* - #Check LiveMigrationPerf option and Limit (Need more research on how the bandwidth works as it seems unchanged) - Get-Cluster -Name $ClusterName | Select-Object *SMB* + #Configure dcbxmode to be host in charge (default is firmware in charge) on mellanox adapters (Dell recommendation) + #Caution: This disconnects 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 'Dcbxmode' -DisplayValue 'Host in charge' + } + } - #Configure SMB Bandwidth Limits for Live Migration https://techcommunity.microsoft.com/t5/Failover-Clustering/Optimizing-Hyper-V-Live-Migrations-on-an-Hyperconverged/ba-p/396609 - #note: this should be normally configured with NetATC... docs needed https://techcommunity.microsoft.com/t5/networking-blog/network-atc-what-s-coming-in-azure-stack-hci-22h2/ba-p/3598442 - #install feature - Invoke-Command -ComputerName $servers -ScriptBlock {Install-WindowsFeature -Name "FS-SMBBW"} - #Calculate 40% of capacity of NICs in vSwitch (considering 2 NICs, if 1 fails, it will not consume all bandwith, therefore 40%) - $Adapters=(Get-VMSwitch -CimSession $Servers[0]).NetAdapterInterfaceDescriptions - $BytesPerSecond=((Get-NetAdapter -CimSession $Servers[0] -InterfaceDescription $adapters).TransmitLinkSpeed | Measure-Object -Sum).Sum/8 - Set-SmbBandwidthLimit -Category LiveMigration -BytesPerSecond ($BytesPerSecond*0.4) -CimSession $Servers + #Configure SMB Bandwidth Limits for Live Migration https://techcommunity.microsoft.com/t5/Failover-Clustering/Optimizing-Hyper-V-Live-Migrations-on-an-Hyperconverged/ba-p/396609 + #note: this should be normally configured with NetATC... docs needed https://techcommunity.microsoft.com/t5/networking-blog/network-atc-what-s-coming-in-azure-stack-hci-22h2/ba-p/3598442 + #install feature + Invoke-Command -ComputerName $servers -ScriptBlock {Install-WindowsFeature -Name "FS-SMBBW"} + #Calculate 40% of capacity of NICs in vSwitch (considering 2 NICs, if 1 fails, it will not consume all bandwith, therefore 40%) + $Adapters=(Get-VMSwitch -CimSession $Servers[0]).NetAdapterInterfaceDescriptions + $BytesPerSecond=((Get-NetAdapter -CimSession $Servers[0] -InterfaceDescription $adapters).TransmitLinkSpeed | Measure-Object -Sum).Sum/8 + Set-SmbBandwidthLimit -Category LiveMigration -BytesPerSecond ($BytesPerSecond*0.4) -CimSession $Servers + } #endregion #region Create Fault Domains (just an example) https://docs.microsoft.com/en-us/windows-server/failover-clustering/fault-domains @@ -981,6 +1172,97 @@ if ((Get-CimInstance -ClassName win32_computersystem -CimSession $Servers[0]).Ma } #endregion -#region collect diagnostic data - Send-DiagnosticData +#region troubleshooting + #check devices drivers + Get-CimInstance -ClassName Win32_PnPSignedDriver -CimSession $Servers | Select-Object DeviceName,DriverDate,DriverVersion, Manufacturer,PSComputerName | Out-GridView + + #check OS Build Number + $RegistryPath = 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\' + $ComputersInfo = Invoke-Command -ComputerName $servers -ScriptBlock { + Get-ItemProperty -Path $using:RegistryPath + } + $ComputersInfo | Select-Object PSComputerName,CurrentBuildNumber,UBR + + #check last driver update status + Invoke-Command -ComputerName $Servers -ScriptBlock { + #display result + $json=Get-Content "C:\ProgramData\Dell\DELL System Update\dell_dup\DSU_STATUS.json" | ConvertFrom-Json + $output=$json.SystemUpdateStatus.updateablecomponent #| Select-Object Name,Version,Baselineversion,UpdateStatus,RebootRequired + Return $output + } | Out-GridView + + #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 + $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*" ){ + Write-Output "No updates found" + $DellUpdates=$null + }else{ + $DellUpdateRequired=$true + $DellUpdates=$json.SystemUpdateStatus.updateablecomponent | Select-Object Name,Version,Baselineversion,UpdateStatus,RebootRequired + } + + #scan for microsoft updates + $SearchCriteriaAllUpdates = "IsInstalled=0 and DeploymentAction='Installation' or + IsPresent=1 and DeploymentAction='Uninstallation' or + IsInstalled=1 and DeploymentAction='Installation' and RebootRequired=1 or + IsInstalled=0 and DeploymentAction='Uninstallation' and RebootRequired=1" + $Searcher = New-Object -ComObject Microsoft.Update.Searcher + $SearchResult = $Searcher.Search($SearchCriteriaAllUpdates).Updates + if ($SearchResult.Count -gt 0){ + $MicrosoftUpdateRequired=$True + }else{ + $MicrosoftUpdateRequired=$False + } + + #grab windows version + $ComputersInfo = Get-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\' + + $Output=@() + $Output += [PSCustomObject]@{ + "DellUpdateRequired" = $DellUpdateRequired + "DellUpdates" = $DellUpdates + "MicrosoftUpdateRequired" = $MicrosoftUpdateRequired + "MicrosoftUpdates" = $SearchResult + "ComputerName" = $env:COMPUTERNAME + "CurrentBuildNumber" = $ComputersInfo.CurrentBuildNumber + "UBR" = $ComputersInfo.UBR + } + return $Output + } + $ScanResult + #endregion + + #Check cluster networks + Get-ClusterNetwork -Cluster $clustername + + #Verify Networking + #validate vSwitch + Get-VMSwitch -CimSession $servers | Select-Object Name,IOV*,NetAdapterInterfaceDescriptions,ComputerName + #validate vNICs + Get-VMNetworkAdapter -CimSession $servers -ManagementOS + #validate vNICs to pNICs mapping + Get-VMNetworkAdapterTeamMapping -CimSession $servers -ManagementOS | Select-Object ComputerName,NetAdapterName,ParentAdapter + #validate JumboFrames setting + Get-NetAdapterAdvancedProperty -CimSession $servers -DisplayName "Jumbo Packet" + #verify RDMA settings + Get-NetAdapterRdma -CimSession $servers | Sort-Object -Property PSComputerName,Name + #validate if VLANs were set + Get-VMNetworkAdapterVlan -CimSession $Servers -ManagementOS + #VLANs in NetATC are set with VMNetworkAdapterIsolation + Get-VMNetworkAdapterIsolation -CimSession $Servers -ManagementOS + #verify ip config + Get-NetIPAddress -CimSession $servers -InterfaceAlias vEthernet* -AddressFamily IPv4 | Sort-Object -Property PSComputerName,InterfaceAlias | Select-Object PSComputerName,InterfaceALias,IPAddress + #Validate DCBX setting + Invoke-Command -ComputerName $servers -ScriptBlock {Get-NetQosDcbxSetting} | Sort-Object PSComputerName | Select-Object PSComputerName,Willing + #validate policy (no result since it's not available in VM) + Invoke-Command -ComputerName $servers -ScriptBlock {Get-NetAdapterQos | Where-Object enabled -eq true} | Sort-Object PSComputerName + #Validate QOS Policies + Get-NetQosPolicy -CimSession $servers | Sort-Object PSComputerName,Name | Select-Object PSComputerName,NetDirectPort,PriorityValue + #validate flow control setting + Invoke-Command -ComputerName $servers -ScriptBlock {Get-NetQosFlowControl} | Sort-Object -Property PSComputername,Priority | Select-Object PSComputerName,Priority,Enabled + #validate QoS Traffic Classes + Invoke-Command -ComputerName $servers -ScriptBlock {Get-NetQosTrafficClass} |Sort-Object PSComputerName,Name |Select-Object PSComputerName,Name,PriorityFriendly,Bandwidth #endregion \ No newline at end of file diff --git a/Scenarios/AzSHCI and MDT/Scenario.ps1 b/Scenarios/AzSHCI and MDT/Scenario.ps1 index 18a75851..eaab84d9 100644 --- a/Scenarios/AzSHCI and MDT/Scenario.ps1 +++ b/Scenarios/AzSHCI and MDT/Scenario.ps1 @@ -34,7 +34,8 @@ $Files+=@{Uri="https://go.microsoft.com/fwlink/?linkid=2166133" ; FileName="adkwinpesetup.exe" ; Description="WindowsPE for Windows 11 21H2"} $Files+=@{Uri="https://download.microsoft.com/download/3/3/9/339BE62D-B4B8-4956-B58D-73C4685FC492/MicrosoftDeploymentToolkit_x64.msi" ; FileName="MicrosoftDeploymentToolkit_x64.msi" ; Description="Microsoft Deployment Toolkit"} #$Files+=@{Uri="https://software-download.microsoft.com/download/pr/AzureStackHCI_17784.1408_EN-US.iso" ; FileName="AzureStackHCI_17784.1408_EN-US.iso" ; Description="Azure Stack HCI ISO"} - $Files+=@{Uri="https://software-static.download.prss.microsoft.com/sg/download/888969d5-f34g-4e03-ac9d-1f9786c66749/AzureStackHCI_20348.587_en-us.iso" ; FileName="AzureStackHCI_20348.587_en-us.iso" ; Description="Azure Stack HCI ISO"} + #$Files+=@{Uri="https://software-static.download.prss.microsoft.com/sg/download/888969d5-f34g-4e03-ac9d-1f9786c66749/AzureStackHCI_20348.587_en-us.iso" ; FileName="AzureStackHCI_20348.587_en-us.iso" ; Description="Azure Stack HCI ISO"} + $Files+=@{Uri="https://software-static.download.prss.microsoft.com/dbazure/988969d5-f34g-4e03-ac9d-1f9786c66751/20349.1129.221007-2120.fe_release_hciv3_svc_refresh_SERVERAZURESTACKHCICOR_OEMRET_x64FRE_en-us.iso" ; FileName="AzureStackHCI_20349.1129_en-us.iso" ; Description="Azure Stack HCI ISO"} $Files+=@{Uri="https://go.microsoft.com/fwlink/?linkid=866658" ; FileName="SQL2019-SSEI-Expr.exe" ; Description="SQL Express 2019"} #$Files+=@{Uri="https://aka.ms/ssmsfullsetup" ; FileName="SSMS-Setup-ENU.exe" ; Description="SQL Management Studio"} foreach ($file in $files){ @@ -176,7 +177,7 @@ } #Import Operating System - $ISO = Mount-DiskImage -ImagePath "$downloadfolder\AzureStackHCI_20348.587_en-us.iso" -PassThru + $ISO = Mount-DiskImage -ImagePath "$downloadfolder\AzureStackHCI_20349.1129_en-us.iso" -PassThru $ISOMediaPath = (Get-Volume -DiskImage $ISO).DriveLetter+':\' Import-mdtoperatingsystem -path "DS001:\Operating Systems" -SourcePath $ISOMediaPath -DestinationFolder "Azure Stack HCI SERVERAZURESTACKHCICORE x64" -Verbose @@ -209,7 +210,7 @@ #region configure MDT run-as account #create identity for MDT $DefaultOUPath=(Get-ADDomain).UsersContainer - New-ADUser -Name MDTUser -AccountPassword (ConvertTo-SecureString "LS1setup!" -AsPlainText -Force) -Enabled $True -Path $DefaultOUPath + New-ADUser -Name MDTUser -AccountPassword (ConvertTo-SecureString "LS1setup!" -AsPlainText -Force) -Enabled $True -Path $DefaultOUPath -PasswordNeverExpires $True #add FileShare permissions for MDT Account Invoke-Command -ComputerName $MDTServer -ScriptBlock { @@ -304,6 +305,8 @@ SkipBDDWelcome=YES Invoke-Command -ComputerName $MDTServer -ScriptBlock { Wdsutil /Set-TransportServer /EnableTftpVariableWindowExtension:No } + + #In case you have #endregion #region configure MDT Monitoring @@ -827,7 +830,7 @@ $HVHosts #$Credentials=Get-Credential $password = ConvertTo-SecureString "LS1setup!" -AsPlainText -Force $Credentials = New-Object System.Management.Automation.PSCredential ("LabAdmin", $password) -$idrac_ips="192.168.100.130","192.168.100.131" +$idrac_ips="192.168.100.130","192.168.100.131","192.168.100.139","192.168.100.140" $Headers=@{"Accept"="application/json"} $ContentType='application/json' function Ignore-SSLCertificates @@ -900,6 +903,8 @@ foreach ($idrac_ip in $idrac_ips){ $HVHosts = @() $HVHosts+=@{ComputerName="AxNode1" ;IPAddress="10.0.0.120" ; MACAddress="0C:42:A1:DD:57:DC" ; GUID="4C4C4544-004D-5410-8031-B4C04F373733"} $HVHosts+=@{ComputerName="AxNode2" ;IPAddress="10.0.0.121" ; MACAddress="0C:42:A1:DD:57:C8" ; GUID="4C4C4544-004D-5410-8033-B4C04F373733"} + $HVHosts+=@{ComputerName="AxNode3" ;IPAddress="10.0.0.122" ; MACAddress="10:70:FD:08:E6:B4" ; GUID="4C4C4544-004D-5810-8046-B2C04F574D33"} + $HVHosts+=@{ComputerName="AxNode4" ;IPAddress="10.0.0.123" ; MACAddress="10:70:FD:08:E6:BC" ; GUID="4C4C4544-004D-5810-8046-B3C04F574D33"} #> #grab machines that attempted to boot in last 5 minutes and create hash table. @@ -1186,7 +1191,7 @@ $TextToSearch #$Credentials=Get-Credential $password = ConvertTo-SecureString "LS1setup!" -AsPlainText -Force $Credentials = New-Object System.Management.Automation.PSCredential ("LabAdmin", $password) -$idrac_ips="192.168.100.130","192.168.100.131" +$idrac_ips="192.168.100.130","192.168.100.131","192.168.100.139","192.168.100.140" $Headers=@{"Accept"="application/json"} $ContentType='application/json' function Ignore-SSLCertificates @@ -1382,8 +1387,8 @@ foreach ($idrac_ip in $idrac_ips){ #in real world scenairos you can have hash table like this: <# $HVHosts = @() - $HVHosts+=@{ComputerName="R440Node1" ;IPAddress="10.0.0.122" ; MACAddress="34:80:0D:91:0B:66" ; GUID="4C4C4544-0051-5610-8056-B8C04F323333"} - $HVHosts+=@{ComputerName="R440Node2" ;IPAddress="10.0.0.123" ; MACAddress="34:80:0D:91:0B:54" ; GUID="4C4C4544-0051-5610-8054-B8C04F323333"} + $HVHosts+=@{ComputerName="R440Node1" ;IPAddress="10.0.0.131" ; MACAddress="34:80:0D:91:0B:66" ; GUID="4C4C4544-0051-5610-8056-B8C04F323333"} + $HVHosts+=@{ComputerName="R440Node2" ;IPAddress="10.0.0.132" ; MACAddress="34:80:0D:91:0B:54" ; GUID="4C4C4544-0051-5610-8054-B8C04F323333"} #> #grab machines that attempted to boot in last 5 minutes and create hash table. diff --git a/Scenarios/AzSHCI and Offline Environment/Scenario.ps1 b/Scenarios/AzSHCI and Offline Environment/Scenario.ps1 index 1a807bc9..8c1bb43e 100644 --- a/Scenarios/AzSHCI and Offline Environment/Scenario.ps1 +++ b/Scenarios/AzSHCI and Offline Environment/Scenario.ps1 @@ -21,6 +21,8 @@ foreach ($PowerShellModule in $PowerShellModules){ Save-Module -Name $PowerShellModule -Path $PSModulesDownloadFolder } + #grab nuget packages + Install-PackageProvider -Name NuGet -Force #grab some binaries to tools folder $ToolsDownloadFolder="$Env:UserProfile\Downloads\Tools\" @@ -31,6 +33,8 @@ & "$ToolsDownloadFolder\DownloadLatestCUs.ps1" #grab windows admin center Start-BitsTransfer -Source https://aka.ms/WACDownload -Destination "$ToolsDownloadFolder\WindowsAdminCenter.msi" + #grab latest defender update + Start-BitsTransfer -Source "https://go.microsoft.com/fwlink/?LinkID=121721&arch=x64" -Destination "$ToolsDownloadFolder\mpam-fe.exe" #grab dell tools and updates $DellToolsDownloadFolder="$Env:UserProfile\Downloads\Dell\" @@ -155,7 +159,9 @@ if (-not (Test-NetConnection -ComputerName $Server -CommonTCPPort SMB).TcpTestSucceeded){ Enable-NetFirewallRule -Name FPS-SMB-In-TCP -CimSession $Server } - Copy-item -Path $Update.FullName -Destination \\$Server\C$\users\$env:USERNAME\Downloads + foreach ($update in $Updates){ + Copy-item -Path $Update.FullName -Destination \\$Server\C$\users\$env:USERNAME\Downloads + } } Invoke-Command -ComputerName $Servers -ScriptBlock { @@ -163,42 +169,54 @@ Start-Process -FilePath "$env:systemroot\System32\wusa.exe" -ArgumentList "$env:userprofile\Downloads\$($Update.Name) /quiet /norestart" -Wait } } -#endregion + #Check pending reboot + Invoke-CimMethod -CimSession $Servers -Namespace "root/Microsoft/Windows/WindowsUpdate" -ClassName "MSFT_WUSettings" -MethodName IsPendingReboot -#region perform Dell Drivers update https://www.dell.com/support/home/en-us/product-support/product/system-update/docs - #region prepare DSU binaries - #copy dell tools to c:\Dell - $DellToolsDownloadFolder="$Env:UserProfile\Downloads\Dell\" + #install defender definition update + #copy it to servers (in this case failover clustering is not yet installed-firewall will not allow SMB, therefore enabling smb rule if not reachable) foreach ($Server in $Servers){ if (-not (Test-NetConnection -ComputerName $Server -CommonTCPPort SMB).TcpTestSucceeded){ Enable-NetFirewallRule -Name FPS-SMB-In-TCP -CimSession $Server } - Copy-item -Path $DellToolsDownloadFolder -Destination \\$Server\C$\ -Recurse + Copy-item -Path "$ToolsDownloadFolder\mpam-fe.exe" -Destination \\$Server\C$\users\$env:USERNAME\Downloads } + #install + Invoke-Command -ComputerName $Servers -ScriptBlock { + Start-Process -FilePath "$env:userprofile\Downloads\mpam-fe.exe" -Wait + } +#endregion - #install DSU on servers - Invoke-Command -ComputerName $Nodes -ScriptBlock { - Start-Process -FilePath "c:\Dell\DSU.exe" -ArgumentList "/silent" -Wait - } +#region perform Dell Drivers update https://www.dell.com/support/home/en-us/product-support/product/system-update/docs + #copy dell tools to c:\Dell + $DellToolsDownloadFolder="$Env:UserProfile\Downloads\Dell\" + foreach ($Server in $Servers){ + if (-not (Test-NetConnection -ComputerName $Server -CommonTCPPort SMB).TcpTestSucceeded){ + Enable-NetFirewallRule -Name FPS-SMB-In-TCP -CimSession $Server + } + Copy-item -Path $DellToolsDownloadFolder -Destination \\$Server\C$\ -Recurse + } - #install dell updates - Invoke-Command -ComputerName $Servers -ScriptBlock { - #create answerfile for DU - $content='@ - a - c - @' - Set-Content -Path "C:\Dell\answer.txt" -Value $content -NoNewline - #Create CMD to install updates - $content='"C:\Program Files\Dell\DELL System Update\DSU.exe" --source-location="C:\Dell" --source-type="Repository" --catalog-location="C:\Dell\ASHCI-Catalog.xml" --ic-location="C:\Dell\IC.exe" --apply-upgrades