Here is a quick and dirty PowerShell script to parse the output of the rpowermt command used to manage PowerPath/VE on ESX (for EMC arrays). I wrote the code quickly to solve a particular problem, but if I get requests I could extend it to parse the rest of the output and do so in a little more robust fashion.
Why do this? I am in the middle of migrations between frames and I needed an easy way to determine what needed moved when the storage admin said move all LUNs from CLARiiON XXXX to the new LUNs on YYYY – and make sure to move LUN 41 to LUN 88.
By parsing the output of rpowermt I could more easily determine the ID of the LUNs they indicated and map that to the extent properties of my datastores to determine what needed to move.
Two step usage:
- rpowermt host=esx001 display dev=all > esx001_lundata.txt
- $lunInfo = .\SimplePowerVeParse esx001_lundata.txt
Alternate ways of accomplishing the same thing:
- The Storage Viewer plugin from EMC would be helpful in determining this from the GUI, but due to political reasons this is not yet deployed in production.
- I originally wanted to try and talk to the CIM provider for PowerPath, but quickly found that the Get-WSManInstance cmdlet’s authentication assumptions were very Windows centric.
The script
# Naive parsing of the output of rpowermt for PowerPath/VE against CLARiiON and Symmetrix devices param ( $fileName = "esx001_luninfo.txt" ) # Easily re-usable data object Function LunInfo { "" | Select-Object "PseudoName", "ArrayType", "ArrayID", "LunID", "LunLabel" } # Generic dispatcher to more detailed parsers Function Parse-LunInfo { param ( [String[]]$info ) if ($info.Length -lt 2) { throw "Insufficient rpowermt input to determine device type." } switch -regex ($info[1]) { '^CLARiiON' {Parse-CLARiiONInfo $info} '^Symmetrix' {Parse-SymmetrixInfo $info} default {throw "Unhandled device type."} } } # Parse CLARiiON lun information Function Parse-CLARiiONInfo { param ( [String[]]$info ) if ($info.Length -lt 3) { throw "Insufficient data for the CLARiiON data block." } $lunInfo = LunInfo $lunInfo.ArrayType = "CLARiiON" # Parse the first line if ($info[0] -match 'Pseudo name=(?<Name>\w+\d+)') { $lunInfo.PseudoName = $Matches["Name"] } else { throw "Invalid pseudo name data for CLARiiON." } # Parse the second line if ($info[1] -match 'CLARiiON ID=(?<ArrayId>[\w\d]+)') { $lunInfo.ArrayID = $Matches["ArrayId"] } else { throw "Invalid CLARiiON ID line." } # Third line if ($info[2] -match 'Standard UID=(?<LunID>.+)\s\[(?<LunLabel>.*)\]') { $lunInfo.LunID = $Matches["LunID"] $lunInfo.LunLabel = $Matches["LunLabel"] } else { throw "Invalid CLARiiON Standard UID line." } $lunInfo } # Parse Symmetrix LUN information Function Parse-SymmetrixInfo { param ( [String[]]$info ) if ($info.Length -lt 4) { throw "Insufficient data for the CLARiiON data block." } $lunInfo = LunInfo $lunInfo.ArrayType = "Symmetrix" # Parse the first line if ($info[0] -match 'Pseudo name=(?<Name>\w+\d+)') { $lunInfo.PseudoName = $Matches["Name"] } else { throw "Invalid pseudo name data for Symmetrix." } # Parse the second line if ($info[1] -match 'Symmetrix ID=(?<ArrayId>\d+)') { $lunInfo.ArrayID = $Matches["ArrayId"] } else { throw "Invalid Symmetrix ID line." } # Third line if ($info[2] -match 'Logical device ID=(?<LunLabel>[\w\d]+)') { $lunInfo.LunLabel = $Matches["LunLabel"] } else { throw "Invalid Symmetrix logical device ID line." } # Fourth line if ($info[3] -match 'Standard UID=(?<LunID>naa\.\d+)') { $lunInfo.LunID = $Matches["LunID"] } else { throw "Invalid CLARiiON Standard UID line." } $lunInfo } $fileData = Get-Content $fileName $elementData = @() # Assuming information blocks are data are separated by a blank line. foreach ($line in $fileData) { if ($line -eq "") { if ($elementData.Length -gt 0) { Parse-LunInfo $elementData $elementData = @() } } else { $elementData += $line } } # Catch anything leftover at the end. if ($elementData.Length -gt 0) { Parse-LunInfo $elementData } |