Troubles with Get-MPIOSetting in Windows Server

There have been a number of customers that have hit an issue with the Test-WindowsBestPractices cmdlet which is part of the PowerShell Toolkit. The problem started to manifest in the November 2017 timeframe when a Cumulative Update (CU) was rolled out across Windows Server 2012, 2012 R2 and 2016. I have confirmed this bug with Microsoft and have an open case with them to keep status on when (and if) a fix will be rolled into the previously mentioned versions of Windows Server.

I have confirmed that this issue is fixed in the latest Insider Preview builds of 17093 or greater. To explain the root of the issue below are two examples of running Get-MPIOSetting on Windows Server 2016 and the other on Windows Server 10.0.17093.

Windows Server 2016

In this example Get-MPIOSetting is output to a variable $mpio. Prior to the issue coming up using this method the $mpio variable was addressable to get/set the individual properties. Using this method after the Windows Server CU was applied shows that the individual properties can no longer be retrieved directly.

Windows Server 10.0.17093

Using the latest version of the Windows Server Insider Preview and applying the same method as explained for the Windows Server 2016 shows that the properties are now properly retrieved.

The impact of this issue in Windows Server 2012, 2012 R2 and 2016 for Pure Storage customers who use the Test-WindowsBestPractices cmdlet is that it simply doesn’t work properly. I have tried a number of methods that I’m not particularly fond of like substring. There I said it. Every line of PowerShell that used ____. Below is the new version that I implemented in the PowerShell Toolkit 1802.22. This checks for Windows Server version and then substrings the results of Get-MPIOSetting. Why do I check what version? Well that’s the other problem. I get different substring results between Windows Server 2012 R2 and 2016. The outcome for now is that customers should use Get-MPIOSetting and Set-MPIOSetting directly and not the Test-WindowsBestPractices cmdlet. Details for how use those cmdlets are outlined in the article Step 02 — Configuring Multipath-IO which is part of the Microsoft Platform Guide. The hope is that a fix will come out for the previous versions of Windows Server I mentioned sooner than later.

<# Get-MPIOSetting Output with Best Practices
PS C:\> Get-MPIOSetting

PathVerificationState     : Disabled
PathVerificationPeriod    : 30
PDORemovePeriod           : 30
RetryCount                : 3
RetryInterval             : 1
UseCustomPathRecoveryTime : Enabled
CustomPathRecoveryTime    : 20
DiskTimeoutValue          : 60
#>

switch ((Get-CimInstance Win32_OperatingSystem).version) {
    6.3.9600 { 
        Write-Host "Windows 2012 R2 -- Current MPIO Settings for $($env:COMPUTERNAME)"
        $MPIO = $null
        $MPIO = Get-MPIOSetting | Out-String 
        $MPIO.Replace(" ","")

        $PathVerificationState = $MPIO.Substring(32,8)
        $PDORemovePeriod = $MPIO.Substring(101,2)
        $UseCustomPathRecoveryTime = $MPIO.Substring(195,8)
        $CustomPathRecoveryTime = $MPIO.Substring(232,2)
        $DiskTimeOutValue = $MPIO.Substring(264,2)

        if($PathVerificationState -eq 'Disabled') {
            Write-Host "FAILED" -ForegroundColor Red -NoNewline
            Write-Host ": PathVerificationState is $($PathVerificationState)."
            $resp = Read-Host "REQUIRED ACTION: Set the PathVerificationState to Enabled?"
		    if ($resp.ToUpper() -eq 'Y') {
                Set-MPIOSetting -NewPathVerificationState Enabled
            } else {
                Write-Host "WARNING: Not changing the PathVerificationState to Enabled could cause unexpected path recovery issues." -ForegroundColor Yellow
            }
        } else {
            Write-Host "PASSED" -ForegroundColor Green -NoNewline
            Write-Host ": PathVerificationState is Enabled. No action required."
        }

        if($PDORemovePeriod -ne '30') {
            Write-Host "FAILED" -ForegroundColor Red -NoNewline
            Write-Host ": PDORemovePeriod is set to $($PDORemovePeriod)."
            $resp = Read-Host "REQUIRED ACTION: Set the PDORemovePeriod to 30?"
		    if ($resp.ToUpper() -eq 'Y') {
                Set-MPIOSetting -NewPDORemovePeriod 30
            } else {
                Write-Host "WARNING: Not changing the PathVerificationState to Enabled could cause unexpected path recovery issues." -ForegroundColor Yellow
            }
        } else {
            Write-Host "PASSED" -ForegroundColor Green -NoNewline
            Write-Host ": PDORemovePeriod is set to 30. No action required."
        }

        if($UseCustomPathRecoveryTime -eq 'Disabled') {
            Write-Host "FAILED" -ForegroundColor Red -NoNewline
            Write-Host ": UseCustomPathRecoveryTime is set to $($UseCustomPathRecoveryTime)."
            $resp = Read-Host "REQUIRED ACTION: Set the UseCustomPathRecoveryTime to Enabled?"
		    if ($resp.ToUpper() -eq 'Y') {
                Set-MPIOSetting -CustomPathRecovery Enabled
            } else {
                Write-Host "WARNING: Not changing the UseCustomPathRecoveryTime to Enabled could cause unexpected path recovery issues." -ForegroundColor Yellow
            }
        } else {
            Write-Host "PASSED" -ForegroundColor Green -NoNewline
            #Write-Host ": UseCustomPathRecoveryTime is set to $($UseCustomPathRecoveryTime). No action required."
            Write-Host ": UseCustomPathRecoveryTime is set to Enabled. No action required."

        }

        if($CustomPathRecoveryTime -ne '20') {
            Write-Host "FAILED" -ForegroundColor Red -NoNewline
            Write-Host ": CustomPathRecoveryTime is set to $($CustomPathRecoveryTime)."
            $resp = Read-Host "REQUIRED ACTION: Set the CustomPathRecoveryTime to 20?"
		    if ($resp.ToUpper() -eq 'Y') {
                Set-MPIOSetting -CustomPathRecovery Enabled
            } else {
                Write-Host "WARNING: Not changing the CustomPathRecoveryTime to 20 could cause unexpected path recovery issues." -ForegroundColor Yellow
            }
        } else {
            Write-Host "PASSED" -ForegroundColor Green -NoNewline
            Write-Host ": CustomPathRecoveryTime is set to $($CustomPathRecoveryTime). No action required."
        }

        if($DiskTimeOutValue -ne '60') {
            Write-Host "FAILED" -ForegroundColor Red -NoNewline
            Write-Host ": DiskTimeOutValue is set to $($DiskTimeOutValue)."
            $resp = Read-Host "REQUIRED ACTION: Set the DiskTimeOutValue to 60?"
		    if ($resp.ToUpper() -eq 'Y') {
                Set-MPIOSetting -NewDiskTimeout 60
            } else {
                Write-Host "WARNING: Not changing the DiskTimeOutValue to 60 could cause unexpected path recovery issues." -ForegroundColor Yellow
            }
        } else {
            Write-Host "PASSED" -ForegroundColor Green -NoNewline
            Write-Host ": DiskTimeOutValue is set to $($DiskTimeOutValue). No action required."
        }
    } # Windows 2012 R2
    10.0.14393 { 
        Write-Host "Windows 2016"
        $MPIO = Get-MPIOSetting | Out-String
        $MPIO.Trim()
        $MPIO.Replace(" ","")

        $PathVerificationState = $MPIO.Substring(32,8)
        $PDORemovePeriod = $MPIO.Substring(102,2)
        $UseCustomPathRecoveryTime = $MPIO.Substring(196,8)
        $CustomPathRecoveryTime = $MPIO.Substring(233,2)
        $DiskTimeOutValue = $MPIO.Substring(265,2)
    
            if($PathVerificationState -eq 'Disabled') {
            Write-Host "FAILED" -ForegroundColor Red -NoNewline
            Write-Host ": PathVerificationState is $($PathVerificationState)."
            $resp = Read-Host "REQUIRED ACTION: Set the PathVerificationState to Enabled?"
		    if ($resp.ToUpper() -eq 'Y') {
                Set-MPIOSetting -NewPathVerificationState Enabled
            } else {
                Write-Host "WARNING: Not changing the PathVerificationState to Enabled could cause unexpected path recovery issues." -ForegroundColor Yellow
            }
        } else {
            Write-Host "PASSED" -ForegroundColor Green -NoNewline
            Write-Host ": PathVerificationState is Enabled. No action required."
        }

        if($PDORemovePeriod -ne '30') {
            Write-Host "FAILED" -ForegroundColor Red -NoNewline
            Write-Host ": PDORemovePeriod is set to $($PDORemovePeriod)."
            $resp = Read-Host "REQUIRED ACTION: Set the PDORemovePeriod to 30?"
		    if ($resp.ToUpper() -eq 'Y') {
                Set-MPIOSetting -NewPDORemovePeriod 30
            } else {
                Write-Host "WARNING: Not changing the PathVerificationState to Enabled could cause unexpected path recovery issues." -ForegroundColor Yellow
            }
        } else {
            Write-Host "PASSED" -ForegroundColor Green -NoNewline
            Write-Host ": PDORemovePeriod is set to 30. No action required."
        }

        if($UseCustomPathRecoveryTime -eq 'Disabled') {
            Write-Host "FAILED" -ForegroundColor Red -NoNewline
            Write-Host ": UseCustomPathRecoveryTime is set to $($UseCustomPathRecoveryTime)."
            $resp = Read-Host "REQUIRED ACTION: Set the UseCustomPathRecoveryTime to Enabled?"
		    if ($resp.ToUpper() -eq 'Y') {
                Set-MPIOSetting -CustomPathRecovery Enabled
            } else {
                Write-Host "WARNING: Not changing the UseCustomPathRecoveryTime to Enabled could cause unexpected path recovery issues." -ForegroundColor Yellow
            }
        } else {
            Write-Host "PASSED" -ForegroundColor Green -NoNewline
            #Write-Host ": UseCustomPathRecoveryTime is set to $($UseCustomPathRecoveryTime). No action required."
            Write-Host ": UseCustomPathRecoveryTime is set to Enabled. No action required."
        }

        if($CustomPathRecoveryTime -ne '20') {
            Write-Host "FAILED" -ForegroundColor Red -NoNewline
            Write-Host ": CustomPathRecoveryTime is set to $($CustomPathRecoveryTime)."
            $resp = Read-Host "REQUIRED ACTION: Set the CustomPathRecoveryTime to 20?"
		    if ($resp.ToUpper() -eq 'Y') {
                Set-MPIOSetting -CustomPathRecovery Enabled
            } else {
                Write-Host "WARNING: Not changing the CustomPathRecoveryTime to 20 could cause unexpected path recovery issues." -ForegroundColor Yellow
            }
        } else {
            Write-Host "PASSED" -ForegroundColor Green -NoNewline
            Write-Host ": CustomPathRecoveryTime is set to $($CustomPathRecoveryTime). No action required."
        }

        if($DiskTimeOutValue -ne '60') {
            Write-Host "FAILED" -ForegroundColor Red -NoNewline
            Write-Host ": DiskTimeOutValue is set to $($DiskTimeOutValue)."
            $resp = Read-Host "REQUIRED ACTION: Set the DiskTimeOutValue to 60?"
		    if ($resp.ToUpper() -eq 'Y') {
                Set-MPIOSetting -NewDiskTimeout 60
            } else {
                Write-Host "WARNING: Not changing the DiskTimeOutValue to 60 could cause unexpected path recovery issues." -ForegroundColor Yellow
            }
        } else {
            Write-Host "PASSED" -ForegroundColor Green -NoNewline
            Write-Host ": DiskTimeOutValue is set to $($DiskTimeOutValue). No action required."
        }
    } # Windows 2016
}

Hope this helps explain why there are issues with the Test-WindowsBestPractices cmdlet. Stay tuned for updates.

Thanks,
Barkz

 

Add Comment

Required fields are marked *. Your email address will not be published.

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

This site uses Akismet to reduce spam. Learn how your comment data is processed.