-
Notifications
You must be signed in to change notification settings - Fork 11
Expand file tree
/
Copy pathConvert-LBFO2SET.psm1
More file actions
312 lines (294 loc) · 12.3 KB
/
Convert-LBFO2SET.psm1
File metadata and controls
312 lines (294 loc) · 12.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
<#
Changelog:
29 Aug 2022
- Added Windows Server 2022+ support.
- Fixed an SCVMM compatibilty issue.
-
#>
Function Convert-LBFO2Set
{
<#
.SYNOPSIS
Virtual Switches attached to an LBFO team has been deprecated by Microsoft. Use this tool, to
migrate your team to the alternative teaming solution, Switch Embedded Teaming (SET).
.DESCRIPTION
This script will allow you to migrate a LBFO Team into a SET team. It will also migrate a vSwitch (if added to the LBFO Team)
To a new vSwitch on SET including the vNICs. This enables you to migrate a host with active virtual machines.
.PARAMETER LBFOTeam
The name of the LBFO Team to be migrated
.PARAMETER SETTeam
The name of the SET team to be created (the team does not need to already exist)
.PARAMETER AllowOutage
Use this to allow a migration of a team and vSwitch with only one pNIC. In this case, the migration will incur an outage
for any virtual NICs connected to the team because the underlying pNIC can only be connected to one team at a time
.PARAMETER EnableBestPractices
Use this to set Microsoft recommended best practices for the team and/or Virtual Switch. If this switch is omitted, the
existing settings from the LBFO team will be configured on SET
.EXAMPLE
Convert-LBFO2Set -LBFOTeam NameofLBFOTeam -SETTeam NewSETTeamName
.EXAMPLE
Convert-LBFO2Set TODO
.NOTES
Author: Microsoft Edge OS Networking Team and Microsoft CSS
Please file issues on GitHub @ GitHub.com/Microsoft/Convert-LBFO2SET
.LINK
More projects : https://github.com/topics/msftnet
Windows Networking Blog : https://blogs.technet.microsoft.com/networking/
#>
[CmdletBinding()]
param (
[parameter(Mandatory = $true)]
[String]$LBFOTeam,
[parameter(Mandatory = $true)]
[String]$SETTeam,
[parameter(Mandatory = $False)]
[Switch]$AllowOutage = $false,
[parameter(Mandatory = $False)]
[Switch]$EnableBestPractices = $false
)
Write-Verbose "Collecting data and validating configuration."
# check whether $LBFOTeam is the vSwitch or the LBFO team name bound to a vSwitch
# if there is an LBFO team with the name we simply use that
$isLBFOTeam = Get-NetLbfoTeam -Name $LBFOTeam -ErrorAction SilentlyContinue
if (-NOT $isLBFOTeam)
{
# check to see whether this is a vSwitch
$isvSwitch = Get-VMSwitch $LBFOTeam -ErrorAction SilentlyContinue
if ($isvSwitch)
{
Write-Verbose "LBFOTeam is a vSwitch. Verifying that an LBFO team is attached."
## a vSwitch was found. Now make sure there is an LBFO team attached.
# get the vSwitch adapter(s) based on the InterfaceDescription contained in the vSwitch object
$tmpAdapter = Get-NetAdapter | Where-Object InterfaceDescription -in $isvSwitch.NetAdapterInterfaceDescriptions
# compare to list of LBFO team adapters
$tmpTeam = Get-NetLbfoTeam | Where-Object { $_.Name -in $tmpAdapter.Name -or $_.Name -eq $tmpAdapter.Name }
if ($tmpTeam)
{
# we found the LBFO team attached to the vSwitch! Set that to $LBFOTeam. We'll rediscover the vSwitch later.
$LBFOTeam = $tmpTeam.Name
}
else
{
Throw "An LBFO team associated with $LBFOTeam could not be detected."
}
}
else
{
Throw "Failed to find an LBFO team or vSwitch named $LBFOTeam`."
}
Remove-Variable isLBFOTeam, isvSwitch, tmpAdapter, tmpTeam -ErrorAction SilentlyContinue
}
else
{
Remove-Variable isLBFOTeam -ErrorAction SilentlyContinue
}
# get the path to where the module is stored
$here = Split-Path -Parent (Get-Module -Name Convert-LBFO2SET).Path
if (-NOT $here)
{
throw "Could not find the module path."
}
# detect the version of Windows
$osMajVer = [System.Environment]::OSVersion.Version.Major
$osBldVer = [System.Environment]::OSVersion.Version.Build
switch ($osMajVer)
{
10
{
switch ($osBldVer)
{
# Windows Server 2016
14393 {
$nicReconnBin = "nicReconnect1.exe"
}
# Windows Server 2019+
{ $_ -ge 17763 } {
$nicReconnBin = "nicReconnect5.exe"
}
default
{
throw "This version of Windows is not yet certified for Convert-LBFO2SET."
}
}
}
default
{
throw "A supported version of Windows was not detected."
}
}
#region Data Collection
$configData = @{ NetLBFOTeam = Get-NetLbfoTeam -Name $LBFOTeam -ErrorAction SilentlyContinue }
$ValidationResults = Invoke-Pester -Script "$here\tests\unit\unit.tests.ps1" -Tag PreValidation -PassThru
$ValidationResults | Select-Object -Property TagFilter, Time, TotalCount, PassedCount, FailedCount, SkippedCount, PendingCount | Format-Table -AutoSize
If ($ValidationResults.FailedCount -ne 0)
{
Write-Warning 'Prerequisite checks have failed.'
Write-Warning "`n`nPlease note: if the failure was due to LACP: `n`t - We will intentionally NOT convert this type of team as the new team will not be functional until the port-channel on the physical switch has been modified"
Write-Warning "To continue with an LACP conversion, please break the port-channel on the physical switch and modify the LBFO team to Switch Independent (Set-NetLbfoTeam -TeamingMode SwitchIndependent)"
throw
}
$configData += @{
NetAdapter = Get-NetAdapter -Name $configData.NetLBFOTeam.TeamNics -ErrorAction SilentlyContinue
NetAdapterBinding = Get-NetAdapterBinding -Name $configData.NetLBFOTeam.TeamNics -ErrorAction SilentlyContinue
}
$configData += @{
LBFOVMSwitch = Get-VMSwitch -ErrorAction SilentlyContinue | Where-Object NetAdapterInterfaceGuid -eq $configData.NetAdapter.InterfaceGuid
}
if ($ConfigData.LBFOVMSwitch)
{
$configData += @{
VMNetworkAdapter = Get-VMNetworkAdapter -All | Where-Object SwitchName -EQ $configData.LBFOVMSwitch.Name -ErrorAction SilentlyContinue
}
# Grabbing host vNICs (ManagementOS) attached to the LBFO vSwitch
$configData += @{ HostvNICs = @(Get-VMNetworkAdapter -ManagementOS -SwitchName $configData.LBFOVMSwitch.Name) }
}
#endregion
# EnableIOV should be $true as a best practice unless Hyper-V QoS is in use. Enabling IOV turns the vSwitch Bandwidth mode to 'None' so no legacy QoS
Write-Verbose "Bandwidth Reservation Mode: $($ConfigData.LBFOVMSwitch.BandwidthReservationMode)"
Switch ($ConfigData.LBFOVMSwitch.BandwidthReservationMode)
{
{ 'Absolute' -or 'Weight' } {
If ($configData.LBFOVMSwitch.IovEnabled)
{
$IovEnabled = $true
}
Else
{
$IovEnabled = $false
}
}
'None' { $IovEnabled = $true }
default { $IovEnabled = $false }
}
#region Create new SET team
#TODO: test this logic thuroughly...
if ($AllowOutage -eq $true -and $configData.NetLBFOTeam.Members.Count -eq 1)
{
$NetAdapterNames = $configData.NetLBFOTeam.Members
# Only one pnIC - Destroy the LBFOTeam
Remove-NetLbfoTeam -Name $configData.NetLBFOTeam.Name -Confirm:$false
}
else
{
$NetAdapterNames = $configData.NetLBFOTeam.Members[0]
Remove-NetLbfoTeamMember -Name $configData.NetLBFOTeam.Members[0] -Team $configData.NetLBFOTeam.Name -Confirm:$False
}
Write-Verbose "IOV Enabled: $IovEnabled"
$SETTeamParams = @{
Name = $SETTeam
NetAdapterName = $NetAdapterNames
EnablePacketDirect = $false
EnableEmbeddedTeaming = $true
AllowManagementOS = $false
MinimumBandwidthMode = $($ConfigData.LBFOVMSwitch.BandwidthReservationMode)
EnableIov = $IovEnabled
}
Write-verbose "SETTeam Parameters: $($SETTeamParams | Out-String)"
$vSwitchExists = Get-VMSwitch -Name $SETTeam -ErrorAction SilentlyContinue
if (-NOT $vSwitchExists)
{
New-VMSwitch @SETTeamParams
}
else
{
$VerbosePreference = 'Continue'
Write-Verbose "Team named [$SETTeam] exists and will be used"
$VerbosePreference = 'SilentlyContinue'
}
Remove-Variable SETTeamParams -ErrorAction SilentlyContinue
#endregion
$vmNICs = ($configData.VMNetworkAdapter | Where-Object VMName -ne $Null)
$vNICMigrationNeeded = If ($vmNICs) { $true } else { $false }
# TODO: Add vmNIC and Host vNIC to test cases.
if ($vNICMigrationNeeded) { Connect-VMNetworkAdapter -VMNetworkAdapter $vmNICs -SwitchName $SETTeam -ErrorAction SilentlyContinue }
# migrate host vNIC(s)
Foreach ($HostvNIC in $configData.HostvNics)
{
& "$($here)\helpers\$($nicReconnBin)" -r "$($HostvNIC.Name)" "$SETTeam" | Out-Null
}
# validation to make sure there are no more vmNICs attached
$vmMigGood = Get-VMNetworkAdapter -All | Where-Object SwitchName -EQ $configData.LBFOVMSwitch.Name -ErrorAction SilentlyContinue
if ($vmMigGood)
{
throw "Critical vmNIC migration failure. The following virtual NICs were not migrated to the new SET switch:`n$($vmMigGood | ForEach-Object {
"`n`t$($_.Name) [$(if ($_.VMName) { "$($_.VMName)" }
else { "host" })] "
})"
}
#region Fire and Brimstone
$remainingAdapters = $configData.NetLBFOTeam.Members
if ($configData.LBFOVMSwitch)
{
Remove-VMSwitch -Name $configData.LBFOVMSwitch.Name -Force -ErrorAction SilentlyContinue | Out-Null
}
Remove-NetLbfoTeam -Name $configData.NetLBFOTeam.Name -Confirm:$false -ErrorAction SilentlyContinue
#TODO: May need to check that the switch and / or team actually were removed before moving on
Add-VMSwitchTeamMember -NetAdapterName $remainingAdapters -VMSwitchName $SETTeam
Remove-Variable HostvNIC -ErrorAction SilentlyContinue
<# Temporarily removing till we work through host vNIC migration plan
foreach ($HostvNIC in ($configData.HostvNICs)) {
$NewNetAdapterName = $configData.HostvNICs.$($HostvNIC.Keys).HostvNICNetAdapter.Name
Rename-NetAdapter -Name "$NewNetAdapterName-446f776e2057697468204c42464f" -NewName $NewNetAdapterName
}
#>
#endregion
Write-Verbose "Enable Best Practices Parameter Present: $EnableBestPractices"
if ($EnableBestPractices)
{
$SETInterfaces = (Get-VMSwitchTeam -Name $SETTeam).NetAdapterInterfaceDescription
$SETAdapters = (Get-NetAdapter | Where-Object InterfaceDescription -in $SETInterfaces).Name
Foreach ($interface in $SETAdapters)
{
Reset-NetAdapterAdvancedProperty -Name $interface -ErrorAction SilentlyContinue `
-DisplayName 'NVGRE Encapsulated Task Offload', 'VXLAN Encapsulated Task Offload', 'IPV4 Checksum Offload',
'NetworkDirect Technology', 'Recv Segment Coalescing (IPv4)', 'Recv Segment Coalescing (IPv6)',
'Maximum number of RSS Processors', 'Maximum Number of RSS Queues', 'RSS Base Processor Number',
'RSS Load Balancing Profile', 'SR-IOV', 'TCP/UDP Checksum Offload (IPv4)', 'TCP/UDP Checksum Offload (IPv6)'
Set-NetAdapterAdvancedProperty -Name $interface -DisplayName 'Packet Direct' -RegistryValue 0 -ErrorAction SilentlyContinue
Set-NetAdapterAdvancedProperty -Name $interface -RegistryValue 1 -DisplayName 'Receive Side Scaling', 'Virtual Switch RSS', 'Virtual Machine Queues', 'NetworkDirect Functionality' -ErrorAction SilentlyContinue
}
$NodeOSCaption = (Get-CimInstance -ClassName 'Win32_OperatingSystem').Caption
Switch -Wildcard ($NodeOSCaption)
{
'*Windows Server 2016*' {
$SETSwitchUpdates = @{ DefaultQueueVrssQueueSchedulingMode = 'StaticVRSS' }
$vmNICUpdates = @{ VrssQueueSchedulingMode = 'StaticVRSS' }
$HostvNICUpdates = @{ VrssQueueSchedulingMode = 'StaticVRSS' }
}
'*Windows Server 2019*' {
$SETSwitchUpdates = @{
EnableSoftwareRsc = $true
DefaultQueueVrssQueueSchedulingMode = 'Dynamic'
}
$vmNICUpdates = @{ VrssQueueSchedulingMode = 'Dynamic' }
$HostvNICUpdates = @{ VrssQueueSchedulingMode = 'Dynamic' }
}
}
$SETSwitchUpdates += @{
Name = $SETTeam
DefaultQueueVrssEnabled = $true
DefaultQueueVmmqEnabled = $true
DefaultQueueVrssMinQueuePairs = 8
DefaultQueueVrssMaxQueuePairs = 16
}
$vmNICUpdates += @{
VMName = '*'
VrssEnabled = $true
VmmqEnabled = $true
VrssMinQueuePairs = 8
VrssMaxQueuePairs = 16
}
$HostvNICUpdates += @{
ManagementOS = $true
VrssEnabled = $true
VmmqEnabled = $true
VrssMinQueuePairs = 8
VrssMaxQueuePairs = 16
}
Set-VMSwitch @SETSwitchUpdates
Set-VMSwitchTeam -Name $SETTeam -LoadBalancingAlgorithm HyperVPort
Set-VMNetworkAdapter @HostvNICUpdates
Set-VMNetworkAdapter @vmNICUpdates
Remove-Variable SETSwitchUpdates, vmNICUpdates, HostvNICUpdates, NodeOSCaption -ErrorAction SilentlyContinue
}
}