Cisco.psm1
# Module Declarations # Constants Set-Variable -Name SWDir -Value "SWInfo" -Option Constant -Scope Global -Visibility Private -Description "SWInfo folder"; Set-Variable -Name SWPath -Value "$PWD\$Global:SWDir" -Option Constant -Scope Global -Visibility Private -Description "SWInfo path"; # [String[]]$dcnmHeader = "Fabric", "VSANID", "EnclosureName", "DeviceAlias", "PortWWN", "FCID", "SwitchInterface", "LinkStatus", "Vendor", "SerialNumber", "Model", "FirmwareVer", "DriverVer", "Information"; [String[]]$flogiHeader = "Interface", "VSANID", "FCID", "PortWWN", "NodeWWN", "Flags", "DeviceAlias"; [String[]]$peerHeader = "SwitchWWN", "SwitchIP", "Local", "SwitchID"; [String[]]$portHeader = "Interface", "VSANID", "Desc"; [String[]]$LogInHeader = "Array", "DirPort", "WWN", "NodeName", "PortName", "FCID", "LoggedIN", "OnFabric"; # # Non-Exported Functions . $PSScriptRoot\Local\Export-PSCredentials.ps1 . $PSScriptRoot\Local\Import-PSCredentials.ps1 . $PSScriptRoot\Local\Get-ArrayInfoXML.ps1 # Security Functions function Get-FabricCredentials { Param ([string]$borg) $xmlDB = Get-ArrayInfoXML; if ([string]::IsNullOrEmpty($borg)) { # org value from first record since none specified $unique = $xmlDB.SelectNodes("//Fabric") | Select-Object -Property Org, Fabric, switchID, username, -Unique; $borg = $unique[0].Org } else { $unique = $xmlDB.SelectNodes("//Fabric") | Where-Object { $_.Org -match $borg } | Select-Object -Property Org, Fabric, switchID, username -Unique; } $Script:usr = $unique[0].username $credBase = "-" + $borg + "-Cisco-" + $env:COMPUTERNAME + $credExt; $Script:credfilename = $Global:CRPath + "\" + $Script:usr + $credBase; if ([string]::IsNullOrEmpty($borg) ) { $Script:FabricName = $unique[0].Fabric } else { $Script:FabricName = $FabricName } if (!(Test-Path $Script:credfilename)) { # create cache credential Write-Host "MDS requires credentials for $borg Storage" -ForegroundColor Green Export-PSCredential $Script:usr $credBase Start-Sleep 3; } $Script:cred = Import-PSCredential $Script:credfilename $Script:org = $borg; #TODO: return $cr; } # # SSH Functions function Get-NewSSHSession { param ([string]$mds, [bool]$swlogin = $false) $sess = New-SSHSession -ComputerName $mds -Credential $Script:cred -AcceptKey; $Script:sessID = $sess.SessionID if (($swlogin) -or ($EnablePort)) { Write-Host "SSHSession object $sess created SessionID: $Script:sessID to $mds" -ForegroundColor Green } else { Write-Verbose "SSHSession object $sess created SessionID: $Script:sessID to $mds" } Start-Sleep 2 return $sess; } function Get-SSHStream { param ([string]$switch, [bool]$swlogin = $false) if ($swlogin) { Write-Host " creating SSH stream to $switch" -ForegroundColor White } else { Write-Verbose " creating SSH stream to $switch" } $Script:sshstr = New-SSHShellStream -Index $Script:sessID While (!($Script:sshstr.DataAvailable)) { Start-Sleep -Seconds 2; } $logInInfo = $Script:sshstr.read(); # login verbage } function Stop-SSHsession { param ( [string]$mds, [bool]$swlogin = $false ) if ($Script:sessID -ne $null) { if (($swlogin) -or ($EnablePort)) { Write-Host " SSH processing done, terminating $mds SSH session" -ForegroundColor White } else { Write-Verbose " SSH processing done, terminating $mds SSH session" } $Script:sshstr.Dispose(); Remove-SSHSession -index $Script:sessID | Out-Null $Script:sessID = $null; } } function Set-NXOS-CMD { param ( [string]$mdscmd, [int]$delay, [string]$switch) Write-Verbose "$switch executing: $mdscmd"; [int]$timeout = 0; $Script:sshstr.WriteLine($mdscmd); # Execute command on switch While ((!($Script:sshstr.DataAvailable)) -and ($timeout -lt 3)) { $timeout++; Start-Sleep -Seconds $delay; } if ($Script:sshstr.DataAvailable) { $response = $Script:sshstr.read(); # get cmd output Write-Verbose $response; # If command is successful only $delay lines will exist in the response; # first line the command itself # second line switch command prompt or info prompt line # third line switch command prompt $lineCnt = $response | Measure-Object -Line; if ($lineCnt.Lines -le $delay) { # no errors return $true; } else { return $false; } } else { Write-Host "$switch timeout: $mdscmd" -ForegroundColor Magenta return $false; } } function Set-NXOS-CMDrslt { param ( [string]$mdscmd, [int]$delay, [string]$switch) [int]$timelmt = 30 / $delay; # 30 second timeout in $delay increments [int]$timeout = 0; Write-Verbose " $switch executing: $mdscmd"; #$Script:sshstr.Flush(); $Script:sshstr.WriteLine($mdscmd); # Execute command on switch While ((!($Script:sshstr.DataAvailable)) -and ($timeout -lt $timelmt)) { $timeout++; Start-Sleep -Seconds $delay; } if ($Script:sshstr.DataAvailable) { $response = $Script:sshstr.read(); # get cmd output return $response; } else { Write-Host " $switch timeout: $mdscmd" -ForegroundColor Magenta; return "timeout"; }; } function Get-Zoned { param ([string]$vsan, [string]$wwn) #show zone active vsan XXXX | in "PortWWN" $cmd = "show zone active vsan $vsan " + " | in $wwn n 6" ; Write-Verbose "$switch executing: $cmd"; $Script:sshstr.WriteLine($cmd); # See if $wwn is zoned [int]$timeout = 0; While ((!($Script:sshstr.DataAvailable)) -and ($timeout -lt 3)) { $timeout++; Start-Sleep -Seconds 10; }; if ($Script:sshstr.DataAvailable) { $timeout = 0; $zoneInfo = $Script:sshstr.read(); # get cmd output # If wwn not in a zone only 2 lines will exist in the cmd response; # first line the command itself # second line switch command prompt $lineCnt = $zoneInfo | Measure-Object -Line; } if ($timeout -ne 0) { Write-Host "timeout: $cmd" -ForegroundColor Magenta return $false; } if ($lineCnt.Lines -lt 3) { # not zoned return $true; } else { return $false; } } function Set-PortValue { param ([string]$pv) ($blade,$port) = $pv.Split("/"); if ($blade.Length -eq 4) { $blade = $blade.Substring(2,2) } else { $blade = "0" + $blade.Substring(2,1) } if ($port.Length -eq 1) { $port = "0" + $port }; $tmp = $blade + $port; return $tmp; } function Set-PortName { param ([string]$pname) ($x1, $x2, $x3) = $pname -split '[\n]'; $pname = $x2; $pname = $pname.Trim(); ($d1,$d2,$d3,$des) = $pname.Split(" "); if ([string]::IsNullOrEmpty($SwitchName)) { ($portname,$leftover) = $des -split '[" ",_\-]'; # split on space, comma, underscore, or dash } else { ($portname,$leftover) = $des -split '[" "]'; # split on space only } if ($portname.Length -le 0) { $portname = "unknown"} return $portname.ToLower(); } function Get-ZoneName { param ( [string]$mdscmd, [int]$delay, [string]$mds, [string]$pwwn) $cmdRslt = Set-NXOS-CMDrslt $mdscmd $delay $mds; if ($cmdRslt -eq "timeout") { return $cmdRslt}; $fileName = "$mds" + "-temp.txt"; $filePath = $Script:FBPath + "\" + $fileName; if (Test-Path $filePath) { Remove-Item -Path $filePath }; $cmdRslt -replace "`r`n","`n" | set-content -path $filePath $zoneName = $null; get-content -Path $filePath | ForEach-Object { # process each input line if ($_ -match "^zone name") { $zline = $_; ($z1,$z2,$zonename,$z3,$z4) = $zline.Split(); } } Remove-Item -Path $filePath $switchType = $mds.ToCharArray(); if (($switchType[3] -match "h") -and ($zoneName -ne $null)) { # host edge switch & Zoned # device-alias = basename of zone plus last 4 digits of WWN; ($zname,$junk) = $zonename -split '[" ",_\-]'; if ($zname -eq "vipr") { ($zname,$junk) = $junk -split '[" ",_\-]'; } $wwn4 = $pwwn.Substring(18,5); $wwn4 = $wwn4 -replace ":", ""; $zonename = $zname + "_" + $wwn4 $zonename = $zonename.ToLower() } return $zonename; } # # Peer Switch Functions function Move-ToArchive { param ([string]$filePath, [string]$fileName ) $dateTS = Get-Date -Format "yyMMdd-HHmmss" $newName = "$dateTS" + "-" + "$fileName"; $newPath = $Script:FBPath + "\Archive\" + $newName; Move-Item -Path $filePath -Destination $newPath; } function Show-Flogi { begin { [int]$Script:dacnt = 0 } process { $Script:dacnt++ } end { Write-Host " $Script:dacnt Interfaces are missing a Device-Alias assignment" } } function Show-Peer { begin { [int]$reccnt = 0 } process { $reccnt++ $swname = $_.SwitchID Write-Host "Switch: $swname" -ForegroundColor -Green } end { Write-Host " $reccnt switches in $FabricName Fabric" -ForegroundColor Green } } function Convert-FlogiToCSV { param ([string]$fname,[string]$switch) $oldflogi = $null; $csvFile = $FBPath + "\" + "$switch" + "_flogi.csv"; $misFile = $Global:SWPath + "\" + "Flogi_missing.csv"; if (Test-Path $csvFile) { if ($flogiCompare) { $oldflogi = Get-Content -Path $csvFile; # save prior flogi content } Remove-Item -Path $csvFile }; # process each input line get-content -Path $fname | ForEach-Object { # any lines not starting with 'fc', space, or 'po' are ignored if (($_ -match "^fc") -or ($_ -match "^ ") -or ($_ -match "^po")) { $curLine = $_; if ($curline -match "^ ") { # this line contains the device-alias name $bufLine += $_; # replace multiple spaces with a single comma aka CSV file format $buf = $bufLine -replace "\s+", ","; $buf | Out-File -Append -Encoding ascii -FilePath $csvFile $bufLine = $null; } else { if ($bufLine -ne $null) { $buf = $bufLine -replace "\s+", ","; if ($buf -match "$,") { $buf += ",,"} else { $buf += "," } $buf | Out-File -Append -Encoding ascii -FilePath $csvFile $bufLine = $null; } $bufLine = $_; } } } if (Test-Path $fname) { Remove-Item -Path $fname }; $swary = $switch.ToCharArray(); if (($flogiCompare) -and ($oldflogi -ne $null) -and ($swary[3] -eq "s")) { # Compare & Report on flogi differences $newflogi = Get-Content -Path $csvFile; $diff = Compare-Object $newflogi $oldflogi; if ($diff -ne $null) { if ($diff.InputObject.gettype().name -eq "String") { # single record difference if ($diff.SideIndicator -eq "=>") { # missing flogi entry $dateTS = Get-Date -Format "yyMMdd-HHmm" $flogientry = $switch + "," + "$dateTS" + "," + $diff.InputObject; Write-Host " Missing: $flogientry" -ForegroundColor Red $flogientry | Out-File -Append -Encoding ascii -FilePath $misFile } else { $flogientry = $diff.InputObject; Write-Host " New: $flogientry" -ForegroundColor Blue } } else { [int]$sz = $diff.InputObject.Length; for ($i=0; $i -lt $sz; $i++) { if ($diff.SideIndicator[$i] -eq "=>") { # missing flogi entry $dateTS = Get-Date -Format "yyMMdd-HHmm" $flogientry = $switch + "," + "$dateTS" + "," + $diff.InputObject[$i]; Write-Host " Missing: $flogientry" -ForegroundColor Red; $flogientry | Out-File -Append -Encoding ascii -FilePath $misFile } else { $flogientry = $diff.InputObject[$i]; Write-Host " New: $flogientry" -ForegroundColor Blue } } } } } return $csvFile; } function Convert-PeerToCSV { param ([string]$fname) $csvFile = "$FBPath" + "\" + "$FabricName" + ".csv"; $bufLine = $null; get-content -Path $fname | ForEach-Object { # process each input line # any lines not starting with 2 spaces or a space and a digit are ignored if (($_ -match "^ \d") -or ($_ -match "^ ")) { $curLine = $_; if ($curline -match "^ ") { # this line contains the switch name if ($bufLine -notmatch "Local") { $bufLine += ","}; $bufLine += $_; # replace multiple spaces with a single comma aka CSV file format $buf = $bufLine -replace "\s+", ","; $buf = $buf -replace "\[", ""; $buf = $buf -replace "\]", ""; $buf = $buf -replace ".gsm1900.org", ""; $buf | Out-File -Append -Encoding ascii -FilePath $csvFile $bufLine = $null; } else { $bufLine = $_; $bufLine = $bufLine.Trim(); } } } if (Test-Path $fname) { Remove-Item -Path $fname }; return $csvFile; } function Set-DeviceAliasCmds { param ([string]$mds) begin { [int]$reccnt = 0; $cmdFile = $null; } process { $reccnt++; $swint = $_.Interface; $PortWWN = $_.PortWWN; $Flags = $_.Flags; $VSANID = $_.VSANID; if ($cmdFile -eq $null ) { # setup output file $cmdFile = $Script:FBPath + "\" + "$mds" + "_Alias.cmd" if ((Test-Path $cmdFile)) { # Remove old cmdFile Remove-Item $cmdFile | Out-Null } } if ($Script:sshstr.CanWrite) { # Ready to accept SSH commands if (Get-Zoned $VSANID $PortWWN) { # PortWWN is not zoned if (($Flags -eq "P" -or ($Flags -eq ""))) { # a physical port # show int fc1/10 | in "Port description is" $cmd = "show int " + $swint + " | in " + """Port description is"""; $portDes = Set-NXOS-CMDrslt $cmd 5 $switch; if ($portDes -ne "timeout") { $portname = Set-Portname $portDes; } else { $portname = "timeout" } # Create Port alias command to $cmdFile $swport = Set-PortValue $swint; $portAlias = "$portname" + "_" + "$mds" + "_" + "$swport"; $Aliascmd = "device-alias name " + "$portAlias" + " pwwn " + "$PortWWN"; $Aliascmd | Out-File -Append -Encoding ascii -FilePath $cmdFile; if ($portname -eq "timeout") { Write-Host " Review Alias command file for any alias names starting with 'timeout'" -ForegroundColor Blue } } else { # a virtual port NPIV Write-Host " $swint $PortWWN with a port flag of $Flags must be zoned to set a device-alias " -ForegroundColor Red; } } else { # PortWWN is zoned $cmd = "show zone active VSAN $VSANID | in $PortWWN p 3"; $zonename = Get-ZoneName $cmd 5 $mds $PortWWN; if (($zonename -ne $null) -and ($zonename -ne "timeout")) { $Aliascmd = "device-alias name " + "$zonename" + " pwwn " + "$PortWWN"; $Aliascmd | Out-File -Append -Encoding ascii -FilePath $cmdFile; } elseif ($zonename -eq "timeout") { Write-Host " Timeout: $swint $cmd" -ForegroundColor Magenta } else { Write-Host " $swint $PortWWN zonename not found a device-alias will not be created" -ForegroundColor Red } } } } end { } } function New-DeviceAliasCmds { param ([string]$mds) begin { [int]$cmdcnt = 0; [int]$commitcnt = 0; [int]$Script:cfgError = 0; [string]$Script:cfgErrMsg = $null; } process { if (!($Script:cfgError)) { if ($Script:sshstr.CanWrite) { # Ready to accept SSH commands if ($cmdcnt -eq 0) { if (!(Set-NXOS-CMD "show cfs lock" 2 $mds )) { # Check for CFS lock $Script:cfgErrMsg = "CFS is currently locked $mds"; $Script:cfgError = 1; Write-Host $Script:cfgErrMsg -ForegroundColor Red return $null; } if (!(Set-NXOS-CMD "config t" 3 $mds )) { # Enter config mode $Script:cfgErrMsg = "Error entering config mode on $mds"; $Script:cfgError = 2; Write-Host $Script:cfgErrMsg -ForegroundColor Red return $null; } if (!(Set-NXOS-CMD "device-alias database" 2 $mds )) { # Enter Device-Alias DB $Script:cfgErrMsg = "Error entering config mode on $mds"; $Script:cfgError = 3; Write-Host $Script:cfgErrMsg -ForegroundColor Red return $null; } } $cmdcnt++; $cmd = $_; ($cmdName,$cmdParm) = $cmd.Split(); if ($cmdName -match "device-alias") { $commitcnt++; if (!(Set-NXOS-CMD $cmd 2 $mds )) { # Write-Host "$cmd FAILED" -ForegroundColor Red } else { Write-Host "$cmd COMPLETED" -ForegroundColor Green } if ($commitcnt -ge 100) { $commitcnt = 0; if (!(Set-NXOS-CMD "device-alias commit" 2 $mds )) { # Commit Changes Write-Host "device-alias commit ERROR on $mds" -ForegroundColor Red return $null; # exit; } else { Write-Host "device-alias commit COMPLETED" -ForegroundColor Magenta } Start-Sleep -Seconds 10; if (!(Set-NXOS-CMD "device-alias database" 2 $mds )) { # Enter Device-Alias DB Write-Host "Error entering device-alias database on $mds" -ForegroundColor Red return $null; # exit; } } } else { Write-Host "Invalid command: $cmd NOT EXECUTED" -ForegroundColor Red } Start-Sleep -Seconds 1; } } } end { if ($commitcnt -ne 0) { if (!(Set-NXOS-CMD "device-alias commit" 2 $mds )) { # Commit Changes Write-Host "device-alias commit ERROR on $mds" -ForegroundColor Red } else { Write-Host "Remaining device-alias changes committed" -ForegroundColor Magenta } } if (!($Script:cfgError)) { Start-Sleep -Seconds 10; Write-Host "Backing up running configuration from $mds" -ForegroundColor Magenta Set-NXOS-CMD "copy run start fabric" 3 $mds | Out-Null Set-NXOS-CMD "y" 2 $mds | Out-Null Start-Sleep -Seconds 15; Write-Host "Processed $cmdcnt device-alias commands" -ForegroundColor Magenta } else { switch ($cfgError) { 1 { Write-Host " CFS is Locked, try changes after the lock is released " -ForegroundColor Red Write-Host " 'show cfs lock' " -ForegroundColor Blue -NoNewline Write-Host " This will show which switch and user has acquired the lock" } Default { Write-Host " Try logging into the switch and enter the commmand " -ForegroundColor Blue } } } Stop-SSHsession $mds; } } function Get-DeviceAliasCmds { param ([string]$mds) $fName = "$mds" + "_Alias.cmd"; $cmdFile = $Script:FBPath + "\" + "$fName"; if (Test-Path $cmdFile) { Write-Host "Applying device-alias commands on switch, $mds" -ForegroundColor White get-content -Path $cmdFile | New-DeviceAliasCmds $mds if (!($Script:cfgError)) { Move-ToArchive $cmdFile $fname; } } else { Write-Host "$cmdfile no updates required" -ForegroundColor White } } function Get-Flogi-Details { begin {} process { $switch = $_.SwitchID if (([string]::IsNullOrEmpty( $SwitchName)) -or ($SwitchName -eq $switch)) { $sess = Get-NewSSHSession $switch if ($sess.Connected) { $Script:sessID = $sess.SessionID; # Create a SSH stream session Get-SSHstream $switch; $csvFile = $Script:FBPath + "\" + "$switch" + "_flogi.csv"; if ($Script:org -eq "EIT") { # True if host edge switch or switch name explicitly specified via -SwitchName param $swarray = $switch.ToCharArray(); [bool]$switchCtrl = (($swarray[3] -eq "h") -or ($switch -eq $SwitchName)); } else { # True if switch name explicitly specified via -SwitchName param [bool]$switchCtrl = ($switch -eq $SwitchName) } if ((($applyAll) -or (($switchCtrl) -and ($apply)))) { Get-DeviceAliasCmds $switch; # Remove-Item -Path $csvFile | Out-Null; } elseif (($Script:sshstr.CanWrite) -and (!($apply)) ) { # Ready to accept SSH commands # show flogi database details $cmd = "show flogi database details | no-more" Write-Host "$switch executing: $cmd"; $flogiInfo = Set-NXOS-CMDrslt $cmd 2 $switch; # Get flogi details on switch if ($flogiInfo -ne "timeout") { $fileName = $Script:FBPath + "\" + "$switch" + "_flogi-temp.txt"; $flogiInfo | Out-File -Append -Encoding ascii -FilePath $fileName $csvFile = Convert-FlogiToCSV $fileName $switch; if (!($Script:flogiOnly)) { Import-CSV -Path $csvFile -Header $flogiHeader | Where-Object { $_.DeviceAlias -eq ""} | Show-Flogi; # Count the number of flogi records missing a device-alias if ($Script:dacnt -gt 0) { Import-CSV -Path $csvFile -Header $flogiHeader | Where-Object { $_.DeviceAlias -eq "" } | Set-DeviceAliasCmds $switch; # Create device-alias cmd file. } if (Test-Path $fileName) { Remove-Item -Path $fileName; } } } else { Write-Host "Timeout: $switch excuting $cmd" -ForegroundColor Yellow } } Stop-SSHsession $switch; } else { Write-Host "SSH session to $switch failed" -ForegroundColor Red } } } end {} } function Get-CFSPeers { param ([string]$switch, [bool]$swlogin = $false) $sess = Get-NewSSHSession $switch if ($sess.Connected) { $Script:sessID = $sess.SessionID; # Create a SSH stream session Get-SSHstream $switch; if ($Script:sshstr.CanWrite) { # Ready to accept SSH commands # show cfs peers | no-more $cmd = "show cfs peers | no-more" Write-Host "$switch executing: $cmd"; $peerInfo = Set-NXOS-CMDrslt $cmd 2 $switch; # Get flogi details on switch if ($peerInfo -ne "timeout") { $fileName = "$switch" + "_peer-temp.txt"; $filePath = $Script:FBPath + "\" + $fileName; $peerinfo -replace "`r`n","`n" | set-content -path $filePath $csvFile = Convert-PeerToCSV $filePath #Import-CSV -Path $csvFile -Header $peerHeader | Show-Peer Stop-SSHsession $switch; if (!($swLogin)) { Import-CSV -Path $csvFile -Header $peerHeader | Get-Flogi-Details } } } if ($Script:sessID -ne $null) { Stop-SSHsession $switch }; } } function Set-SwitchPorts { param ([string]$mds) begin { if (!(Set-NXOS-CMD "config t" 3 $mds )) { # Enter config mode Write-Host "Error entering config mode on $mds" -ForegroundColor Red Stop-SSHsession $mds return $null; # exit } [int]$portCnt = 0; } process { $portCnt++; $swint = $_.Interface; $portVSAN = $_.VSANID; $portDesc = $_.Desc; $cmd = "VSAN database"; if (!(Set-NXOS-CMD $cmd 3 $mds )) { # Enter interface mode Write-Host "Error entering VSAN database mode for $swint on $mds" -ForegroundColor Red Stop-SSHsession $mds return $null; # exit } $cmd = "VSAN $portVSAN interface $swint"; if (!(Set-NXOS-CMD $cmd 3 $mds )) { # Enter interface mode Write-Host "Error entering VSAN $portVSAN for $swint on $mds" -ForegroundColor Red Stop-SSHsession $mds return $null; # exit } $cmd = "interface $swint"; if (!(Set-NXOS-CMD $cmd 3 $mds )) { # Enter interface mode Write-Host "Error entering interface mode on $mds" -ForegroundColor Red Stop-SSHsession $mds return $null; # exit } $cmd = "switchport description $portDesc"; if (!(Set-NXOS-CMD $cmd 3 $mds )) { # Enter interface mode Write-Host "Error entering switchport on $mds" -ForegroundColor Red Stop-SSHsession $mds return $null; # exit } $cmd = "no shut"; if (!(Set-NXOS-CMD $cmd 3 $mds )) { # Enter interface mode Write-Host "Error entering no shut for $swint on $mds" -ForegroundColor Red Stop-SSHsession $mds return $null; # exit } Write-Host " $swint set to VSAN $portVSAN and enabled" -ForegroundColor White } end { Write-Host " Backing up running configuration from $mds" -ForegroundColor Magenta Set-NXOS-CMD "copy run start fabric" 3 $mds | Out-Null Set-NXOS-CMD "y" 2 $mds | Out-Null Start-Sleep -Seconds 15; Write-Host " Enabled $portCnt ports on $mds" -ForegroundColor Magenta Stop-SSHsession $mds; } } function Get-SwitchPorts { param ([string]$switch, [string]$fileName) $sess = Get-NewSSHSession $switch if ($sess.Connected) { $Script:sessID = $sess.SessionID; # Create a SSH stream session Get-SSHstream $switch; if ($Script:sshstr.CanWrite) { # Ready to accept SSH commands $filePath = $Script:FBPath + "\" + $fileName; Write-Host " Processing $filePath" -ForegroundColor White Import-CSV -Path $filePath -Header $portHeader | Set-SwitchPorts $switch Stop-SSHsession $switch; Move-ToArchive $filePath $fileName; } } } function Get-Symm-Details { begin { function Get-DeviceAlias { param ([string]$wwn) $pwwn = $wwn -replace "([0-9A-Fa-f]{2})",'$1:' # Insert ':' $pwwn = $pwwn.TrimEnd(":",1); # Remove trailing ':' # This code snippet searches all the fabric folders searching for a matching # flogi entry in the files named, "*_flogi.csv". [bool]$flogiFound = $false; Get-ChildItem $Global:SWPath | ForEach-Object { # Processing flogi for each folder in C:\bin\ps\SWInfo $FBPath = $_.PSPath; if (!($flogiFound)) { Get-ChildItem $FBPath -Filter "*_flogi.csv" | Where-Object { $_.Attributes -ne "Directory"} | ForEach-Object { If (Get-Content $_.FullName | Select-String -List -SimpleMatch -Encoding ascii -Pattern $pwwn ) { # $_.FullName; # C:\bin\ps\SWInfo\PX_RN_Fabric_A\pxac103_flogi.csv # $_.PSParentPath; # C:\bin\ps\SWInfo\PX_RN_Fabric_A # $_.PSChildName; # pxac103_flogi.csv $flogiFound = $True; ($switch,$s1) = $_.PSChildName.Split("_"); # GET SWITCH NAME $swChars = $switch.ToCharArray(); # EXTRACT THE RECORD FROM THE FILE $obj = Select-String -Path $_.FullName -List -SimpleMatch -Encoding ascii -Pattern $pwwn # REMOVE SQUARE BRACKETS SURROUNDING THE DEVICE-ALIAS NAME $found = $obj.Line $found = $found -replace "\[", ""; $found = $found -replace "\]", ""; # Write-Host " Flogi Entry: $switch - $found"; # Read-Host "waiting" # CONVERT RECORD INTO CSV OBJECT $flogiObj = ConvertFrom-CSV -InputObject $found -Header $flogiHeader; $DeviceAlias = $flogiObj.DeviceAlias; if (($swChars -eq "h") -and ($DeviceAlias -eq $null)) { # host edge switch & missing a device-alias $portWWN = $pwwn; $VSANID = $flogiObj.VSANID; $swint = $flogiObj.Interface; $cmdFile = $_.PSParentPath + "\" + $switch + "_Alias.cmd"; # Open SSH session & etc... $sess = Get-NewSSHSession $switch if ($sess.Connected) { $Script:sessID = $sess.SessionID; # Create a SSH stream session Get-SSHstream $switch; $cmd = "show zone active VSAN $VSANID | in $PortWWN p 3"; # Write-Host "cmd: $cmd" # Read-Host "waiting" $zonename = Get-ZoneName $cmd 5 $switch $PortWWN; if (($zonename -ne $null) -and ($zonename -ne "timeout")) { $Aliascmd = "device-alias name " + "$zonename" + " pwwn " + "$PortWWN"; $Aliascmd | Out-File -Append -Encoding ascii -FilePath $cmdFile; } elseif ($zonename -eq "timeout") { Write-Host " Timeout: $switch $swint $cmd" -ForegroundColor Magenta } else { Write-Host " $switch $swint $PortWWN zonename not found a device-alias will not be created" -ForegroundColor Red } } Stop-SSHsession $switch; } else { Write-Host " Non host edge switch or Device-Alias already established skipping" } } } } } } } process { $array = $_.Array; $dirport = $_.DirPort; $pwwn = $_.WWN; Write-Host " Evaluating WWN: $pwwn from VMAX $array on $dirport" -ForegroundColor Green Get-DeviceAlias $pwwn } end { } } function Get-SwitchName { param ([string]$fabName) $xmlDB = Get-ArrayInfoXML; $fabricInfo = $xmlDB.SelectNodes("//Fabric") | Where-Object { $_.Fabric -match $fabName } | Select-Object -Property Org, Fabric, switchID, username -Unique; if ($fabricInfo -is [Object]) { return $fabricInfo.switch } else { return $null } } function Add-FabricFolders { param([string]$OrgPath) $xmlDB = Get-ArrayInfoXML; $xmlDB.SelectNodes("//Fabric") | Where-Object { $_.Org -match $Script:org} | ForEach-Object { $folder = $OrgPath + "\" + $_.fabric; if (!(Test-Path $folder)) { New-Item $folder -ItemType Directory | Out-Null; $farchive = $folder + "\archive" New-Item $farchive -ItemType Directory | Out-Null; } } } function Set-Defaults { Get-FabricCredentials $org $Script:SwOrgPath = $Global:SWPath + "-" + $Script:org; # c:\bin\ps\SWInfo-EIT if (!(Test-Path $Script:SwOrgPath)) { New-Item $Script:SwOrgPath -ItemType Directory | Out-Null; # need to create folder for each FabricName in Org Add-FabricFolders $Script:SwOrgPath } } function Show-FabricNames { $xmlDB = Get-ArrayInfoXML; $fabNames = $xmlDB.SelectNodes("//Fabric") | Select-Object -Property Org, Fabric, switchID; $fabNames | Format-Table -AutoSize } function Connect-Switch { begin {} process{ $switch = $_.SwitchID $sess = Get-NewSSHSession $switch $true if ($sess.Connected) { $Script:sessID = $sess.SessionID; # Create a SSH stream session Get-SSHstream $switch $true; Start-Sleep -Seconds 3; Stop-SSHsession $switch $true; } else { Write-Host "SSH session to $switch failed" -ForegroundColor Red } } end {} } # # # Exported Functions # Connect-VeFabric <# .SYNOPSIS Tests the SSH protocol connectivity to switch(s) for all or a specific SAN fabrics within an Organization scope and creates SAN Fabric domain csv file. .DESCRIPTION Establishes a SSH session with the specified Cisco MDS FC switch specific in the fabric record found in the XMLDB. Creates a SAN Fabric domain csv file when the '-createCSV' option is specified. '<execution folder>\SwInfo-<org>\<fabricname>\<fabricname>.csv'. If this file already exists, it is moved to the archive folder and new csv file is created. The SAN Fabric domain csv file contain a record for each switch that is member of the SAN Fabric domain. .PARAMETER FabricName Tests SSH login for each switch that is a member of the FabricName with in the default Orgranization. .PARAMETER Org Is the Organization name responsible for the SAN Fabric(s). This parameter is require to process non-default Organization records. .PARAMETER createCSV Creates the SAN Fabric domain csv file for each SAN Fabric in the Organizaiton domain and then tests ability to log into each switch. Existing csv file is moved to the archive folder. This option is used when initially setting up a new fabric domain folder or when the membership of the fabric domain changes. .INPUTS The XMLDB is accessed to validate the FabricName parameter. The set of switches associated with a SAN Fabric domain is contained in a csv file named, '<execution folder>\SwInfo-<org>\<fabricname>\<fabricname>.csv'. .OUTPUTS Creates SAN Fabric domain csv file for each switch in the SAN Fabric domain. The file is named, '<execution folder>\SwInfo-<org>\<fabricname>\<fabricname>.csv'. .EXAMPLE Connect-VeFabric -FabricName Bow_Fabric_A -createCSV Creates the SAN Fabric domain csv file for the SAN Fabric named, 'Bow_Fabric_A' in the default Organization and then tests SSH login to each switch. If SAN Fabric domain csv file already exists, it is moved to the archive folder. This option must be executed when initially setting up a new SAN Fabric folder or when the membership of the SAN Fabric changes. The SAN fabric folder structure is automatically generated base on the fabric records specified in the XMLDB. .EXAMPLE Connect-VeFabric -createCSV Creates the SAN Fabric domain csv file for each SAN Fabric in the default Organization and tests SSH login to each switch. .EXAMPLE Connect-VeFabric Test SSH login login to each switch in the default SAN Fabric for the default Organization. The default SAN Fabric and Organization is determine by the settings in the first fabric record found in the XMLDB. .EXAMPLE Connect-VeFabric -FabricName ALL Test SSH login to each switch in all SAN Fabrics in the default Organization. The default Organization is determine by the settings in the first fabric record found in the XMLDB. .EXAMPLE Connect-VeFabric -FabricName Mojo_Fabric_A -Org Mojo Tests SSH login to each switch in the SAN Fabric, 'Mojo_Fabric_A' that is associated with the 'Mojo' organization. The '-org' must be used when referencing non-default SAN fabrics. .NOTES Must have the Posh-SSH module installed for processing. Install-Module Posh-SSH -scope currentuser Author: Craig Dayton 0.0.2.0 07/15/2017 : cadayton : Initial release. .LINK https://github.com/cadayton/Venom .LINK http://venom.readthedocs.io #> function Connect-VeFabric { # Update-VeFlogi Params [cmdletbinding()] Param( [Parameter(Position=0, Mandatory=$false, HelpMessage = "Enter a Fabric Name", ValueFromPipeline)] [ValidateNotNullorEmpty()] [string]$FabricName = $null, [Parameter(Position=1, Mandatory=$False, HelpMessage = "Enter an Organization name", ValueFromPipeline)] [ValidateNotNullorEmpty()] [string]$org = $null, [Parameter(Position=2, Mandatory=$False, HelpMessage = "Enter an Organization name", ValueFromPipeline)] [ValidateNotNullorEmpty()] [switch]$createCSV ) # Write-Host "Connect-VeFabric version 0.0.2.0" -ForegroundColor Green Set-Defaults; if ($createCSV) { if ([string]::IsNullOrEmpty($FabricName)) { $Script:FabricName = "All"; } else { $Script:FabricName = $FabricName; } $xmlDB = Get-ArrayInfoXML; if ($Script:FabricName -eq "All") { $xmlDB.SelectNodes("//Fabric") | Where-Object { $_.Org -match $Script:org} | ForEach-Object { $Script:FBPath = $Script:SwOrgPath + "\" + $_.fabric; # Archive current Fabric csvfile if it exists. $csvFile = $_.fabric + ".csv"; $csvPath = $FBPath + "\" + $csvFile; if (Test-Path $csvPath) { Move-ToArchive $csvPath $csvFile} # Generate new Fabric csvfile $switch = $_.switchID; Get-CFSPeers $_.switchID $true } } else { $xmlDB.SelectNodes("//Fabric") | Where-Object { $_.Fabric -match $Script:FabricName -and $_.Org -match $Script:org} | ForEach-Object { $Script:FBPath = $Script:SwOrgPath + "\" + $_.fabric; # Archive current Fabric csvfile if it exists. $csvFile = $_.fabric + ".csv"; $csvPath = $FBPath + "\" + $csvFile; if (Test-Path $csvPath) { Move-ToArchive $csvPath $csvFile} # Generate new Fabric csvfile $switch = $_.switchID; Get-CFSPeers $switch $true } } } if ($Script:FabricName -match "All") { # Switch login for all fabrics Get-ChildItem $Script:SwOrgPath | Where-Object { $_.Attributes -eq "Directory"} | ForEach-Object { # Processing flogi for each folder in C:\bin\ps\SWInfo-<org> $FBPath = $_.PSPath; $fname = $_.PSChildname + ".csv"; $csvFile = $FBPath + "\" + $fname; Import-CSV -Path $csvFile -Header $peerHeader | Connect-Switch } } else { # Switch Login for a specific fabric $xmlDB = Get-ArrayInfoXML; $fabValidate = $xmlDB.SelectNodes("//Fabric") | Where-Object { $_.Fabric -match $Script:FabricName -and $_.Org -match $Script:org }; if ($fabValidate -is [Object]) { $FBPath = $Script:SwOrgPath + "\" + $Script:FabricName; $csvFile = $FBPath + "\" + $Script:FabricName + ".csv"; if (Test-Path $csvfile) { Import-CSV -Path $csvFile -Header $peerHeader | Connect-Switch } else { $Script:FBPath = $FBPath; $switch = $fabValidate.switchID; Get-CFSPeers $switch $true; # create fabric domain csv file if (Test-Path $csvFile) { Import-CSV -Path $csvFile -Header $peerHeader | Connect-Switch } else { Write-Host "$csvFile not found" -ForegroundColor Red; Write-Host "Likely a communication problem accessing switch, $fabValidate.switch" -ForegroundColor Green; } } } else { Write-Host "$Script:FabricName was not found in the XMLDB" -ForegroundColor Red Write-Host "Valid Fabric names are: " -ForegroundColor Green Show-FabricNames; } } } # # Enable-VePorts <# .SYNOPSIS Enable ports on a switch. .DESCRIPTION Enables switch port(s) specified in csv file located in the FabricName folder. The csv file consists of 3 fields, interface,VSAN, and Description. interface field: fcx/y where x is the blade number and y is the port number. VSAN field: numeric value of the desired VSAN. Description field: device-alias name followed by a space then the description. i.e. fc1/6,100,bowvmx099_fa05h Engine 1 X X A file titled, <switchname>_enable.csv is expected to found in the FabricName folder. The FabricName folder as the following naming convention. <execution folder>\SwInfo-<org>\<fabricname> Example: C:\bin\ps\SwInfo-Mojo\Mojo_Fabric_A Each port will be added to the VSAN, enabled, and description field set. Once the port(s) have been enabled, the csv file is move to the Archive folder. .PARAMETER FabricName The FabricName containing the switches for the port(s) needing to be enabled within the default Orgranization. .PARAMETER Org Is the Organization name responsible for the SAN Fabric(s). This parameter is require to process non-default Organization records. When the org parameter is not specified, the default organization will be used. The default organization is determined by find the first fabric record in the XMLDB. .INPUTS A csv file titled, <switchname>_enable.csv found in the SAN Fabric folder. .OUTPUTS None. .EXAMPLE Enable-VePorts Searches the default SAN Fabric in the default Organization for files titled, '<switchname>_enable.csv'. Then enables the specified port(s). The default SAN Fabric and Orgranization are set by finding the first fabric record in the XMLDB. .EXAMPLE Enable-VePorts -FabricName Mojo_Fabric_A Searches the SAN Fabric folder <fabricname> in the default Organization for files titled, '<switchname>_enable.csv'. Then enables the specified port(s). The default Organization is determine by the settings in the first fabric record found in the XMLDB. .EXAMPLE Enable-VePorts -FabricName Mojo_Fabric_A -Org Mojo Searches the SAN Fabric folder, '<execution folder>\SwInfo-Mojo\Mojo_Fabric_A' for files titled, '<switchname>_enable.csv'. Then enables the specified port(s). .NOTES Must have the Posh-SSH module installed for processing. Install-Module Posh-SSH -scope currentuser Author: Craig Dayton 0.0.2.0 07/15/2017 : cadayton : Initial release. .LINK https://github.com/cadayton/Venom .LINK http://venom.readthedocs.io #> function Enable-VePorts { # Enable-VeFlogi Params [cmdletbinding()] Param( [Parameter(Position=0, Mandatory=$false, HelpMessage = "Enter a Fabric Name", ValueFromPipeline)] [ValidateNotNullorEmpty()] [string]$FabricName = $null, [Parameter(Position=1, Mandatory=$False, HelpMessage = "Enter an Organization name", ValueFromPipeline)] [ValidateNotNullorEmpty()] [string]$org = $null ) # Write-Host "Enable-VePorts version 0.0.2.0" -ForegroundColor Green Set-Defaults; $Script:FBPath = $Script:SwOrgPath + "\" + $Script:FabricName; Get-ChildItem -Path $Script:FBPath\* -Include *_enable.csv | ForEach-Object { # $fname = $_.PSChildName; ($switch,$s1,$s2) = $fname.Split("_"); Get-SwitchPorts $switch $fname } } # # Update-VeFlogi <# .SYNOPSIS Extract the flogi entries from each switch in the SAN fabrics. .DESCRIPTION Establishes a SSH session with the specified Cisco MDS FC switch in a SAN Fabric and extracts the flogi entries into a csv file. Typically, this cmdlet should be executed at least daily with the SAN Fabric folder version controlled. This will allow one to easily determine the daily changes in the SAN Fabric. .PARAMETER FabricName Is the Fabric name containing a set of switches for which flogi entries will be extracted. .PARAMETER Org Is the Organization name responsible for the SAN Fabric(s) and must be specified when working with non-default SAN Fabric. The default SAN Fabric is determined by the first fabric record in the XMLDB> .INPUTS The XMLDB is accessed to validate the FabricName parameter. The set of switches associated with a SAN Fabric domain is contained in a csv file named, '<execution folder>\SwInfo-<org>\<fabricname>.csv'. .OUTPUTS A flogi csv file for each switch in the SAN Fabric domain. The flogi csv file is named, '<execution folder>\SwInfo-<org>\<fabricname>\<switchname>_flogi.csv'. .EXAMPLE Update-VeFlogi -FabricName Bow_Fabric_A Creates a flogi csv file for each switch in the SAN Fabric named, 'Bow_Fabric_A' for the default Organization. The default SAN Fabric and Organization is determine by the settings in the first fabric record found in the XMLDB. .EXAMPLE Update-VeFlogi -FabricName ALL Creates a flogi csv file for each switch in all SAN Fabrics in the default Organization. The default Organization is determine by the settings in the first fabric record found in the XMLDB. .EXAMPLE Update-VeFlogi -FabricName ALL -Org Mojo Creates a flogi csv file for each switch in all SAN Fabrics in the organization, 'Mojo'. .EXAMPLE Update-VeFlogi Creates a flogi csv file for each switch in the default SAN Fabric for the default Organization. The default SAN Fabric and Organization is determine by the settings in the first fabric record found in the XMLDB. .EXAMPLE Update-VeFlogi -FabricName Mojo_Fabric_A -Org Mojo Creates a flogi csv file for each switch in the SAN Fabric, 'Mojo_Fabric_A' that is associated with the 'Mojo' organization. .NOTES Must have the Posh-SSH module installed for processing. Install-Module Posh-SSH -scope currentuser Author: Craig Dayton 0.0.2.0 07/15/2017 : cadayton : Initial release. .LINK https://github.com/cadayton/Venom .LINK http://venom.readthedocs.io #> function Update-VeFlogi { # Update-VeFlogi Params [cmdletbinding()] Param( [Parameter(Position=0, Mandatory=$false, HelpMessage = "Enter a Fabric Name", ValueFromPipeline)] [ValidateNotNullorEmpty()] [string]$FabricName = $null, [Parameter(Position=1, Mandatory=$False, HelpMessage = "Enter an Organization name", ValueFromPipeline)] [ValidateNotNullorEmpty()] [string]$org = $null ) # Write-Host "Update-VeFlogi version 0.0.2.0" -ForegroundColor Green Set-Defaults; $Script:flogiOnly = $true; if ($Script:FabricName -match "All") { # flogi csv for all fabrics Get-ChildItem $Script:SwOrgPath | Where-Object { $_.Attributes -eq "Directory"} | ForEach-Object { # Processing flogi for each folder in C:\bin\ps\SWInfo-<org> $Script:FBPath = $_.PSPath; $fname = $_.PSChildname + ".csv"; $csvFile = $Script:FBPath + "\" + $fname; Import-CSV -Path $csvFile -Header $peerHeader | Get-Flogi-Details } } else { # flogi csv for a specific fabric $xmlDB = Get-ArrayInfoXML; $fabValidate = $xmlDB.SelectNodes("//Fabric") | Where-Object { $_.Fabric -match $Script:FabricName -and $_.Org -match $Script:org}; if ($fabValidate -is [Object]) { $Script:FBPath = $Script:SwOrgPath + "\" + $Script:FabricName; $csvFile = $Script:FBPath + "\" + $Script:FabricName + ".csv"; if (Test-Path $csvfile) { Import-CSV -Path $csvFile -Header $peerHeader | Get-Flogi-Details } else { Write-Host "$csvFile not found" -ForegroundColor Red Write-Host " "; Write-Host "Execute " -ForegroundColor Blue -NoNewline Write-Host "'Connect-VeFabric -FabricName $Script:FabricName -org $Script:org' " -ForegroundColor Yellow -NoNewline Write-Host "to create the file" -ForegroundColor Blue } } else { Write-Host "$Script:FabricName was not found in the XMLDB" -ForegroundColor Red Write-Host "Valid Fabric names are: " -ForegroundColor Green Show-FabricNames; } } } # # Set-SymmAlias <# block logic not implement # Search /FAInfo/Current_ListLogins.csv # $logInFile = $Global:FAPath + "\" + "Current_ListLogins.csv"; $finfo = Get-ChildItem -Path $logInFile; $lwrite = $finfo.LastWriteTime; $lup = Get-Date -Date $lwrite -Format g; Write-Host "Processing from $logInFile" -ForegroundColor Green; Write-Host " Last Updated: $lup" -ForegroundColor Magenta; Write-Host " "; $logInObj = Get-ArrayLogin -name NULL -loginHost Yes -obj; # Since the initiator is logged into the storage port a zone must exist for it. # Lookup the wwn in the flogi.csv files and assign an alias if needed. $logInObj | Get-Symm-Details; #> # # Set-VeDeviceAlias <# .SYNOPSIS Creates device-aliases on Cisco SAN fabric for initiators and optionally targets missing a device-alias assignment. .DESCRIPTION Establishes a SSH session with the specified Cisco MDS FC switch and sets a device-alias name for initiators and optionally targets without a device-alias. For physical ports NOT in a zone, the new device-alias name is formed using the first node value in the switch's port description field following by switch name and port location. Example device-alias for a phyiscal port: bowWinServer_mdsbow01_0939 For virtual ports (NPIV), the device-alias name will be the first node of the zone name. It is assumed the first node in the zone name is the host name. Example Zone Name: BowWinServer01_HBA1_bowpure001 Example derived Device-Alias name: BowWinServer01_2c1a The last four characters of the device-alias is the last for octets of the WWN. This helps keep all device-alias names unique. The SAN Fabric folder contains a set of flogi csv files which are used for assessing which interfaces are missing a device-alias assignment. A SAN Fabric folder named, <execution folder>\SWInfo-<org>\<fabricname> will be searched for flogi csv files. The naming convention for the flogi csv files is: <switchID>_flogi.csv. A Cisco command file is created in the SAN Fabric folder containing a device-alias commands for each interface missing a device-alias. The command file naming convention is <switch name>_Alias.cmd. All SAN Fabric related files are contained in the specific SAN Fabric folder. Each SAN Fabric folder contains a sub-folder named, Archive for historical tracking of changes. .PARAMETER FabricName Is the SAN Fabric name containing a set of switches to used for processing. If the 'FabricName' option is not specified, then the default FabricName value will be used. The default FabricName value is determined by the first fabric record found in the XMLDB. .PARAMETER Org This option is the organization responsible for the SAN Fabric. If the 'Org' option is not specified, then the default Org value will be used. The default 'Org' value is determined by the first fabric record found in the XMLDB> .PARAMETER apply Executes the device-alias commands found in the file <switch name>_Alias.cmd for all switches in the specified FabricName. If the '-SwitchName' is also specified, only the specified switch name will be processed. .PARAMETER SwitchName Limits the action to the specified SwitchName. .PARAMETER SymmAlias The file /FAInfo/Current_ListLogins.csv is searched for logged in entries containing a Nodename equal "NULL" and a loggedIN value of "Yes". The wwn value of the record is then used to lookup the flogi entry in the /SWInfo/<FabricName> directory. If the flogi entry is not a device-alias, then a device-alias is established. .INPUTS The Fabric domain csv file which is located FabricName folder. <execution path>\SwInfo-<org>\<fabricname>\<fabricname>.csv .OUTPUTS A set files listed below may be found in each Fabric folder. 1. <fabric name>.csv - listing of peer switches in the fabric. 2. <switch name>_flogi.csv - show flogi database details output for each switch. 3. <switch name>_Alias.cmd - set of device-alias commands for device-alias command execution. 4. <switch name>_enable.csv - contains a set of ports requiring to be enabled on the switch. Aged files are moved to the 'Archive' folder in each Fabric named folder. .EXAMPLE Set-DeviceAlias -FabricName Mojo_Fabric_A Will read the input file, <fabric name>.csv and generate an output files, <switch name>_flog.csv and generate files named, <switch name>_Alias.cmd containing a set of device-alias commands. Manually review the files named, <switch name>_Alias.cmd to ensure appropriate device-alias names have been assigned prior to applying the device-alias assignments. .EXAMPLE Set-DeviceAlias -FabricName Mojo_Fabric_A -apply Will read the input file, <switch name>_Alias.cmd and execute the device-alias commands on the switch. .EXAMPLE Set-DeviceAlias -FabricName All Same as example 1 but will process all SAN fabric folders. Once this execution has completed, the following example will apply on the changes. Set-DeviceAlias -FabricName All -apply. .EXAMPLE Set-DeviceAlias -FabricName Mojo_Fabric_A -SwitchName mdshay01 Limits the generation of device-alias command files to the switch named, 'mdshay01' in the SAN Fabric, Mojo_Fabric_A .NOTES Must have the POSH-SSH module installed for processing. Execute the following command to install POSH-SSH module > Install-Module Posh-SSH -scope currentuser Author: Craig Dayton 0.0.2.0 07/15/2017 : cadayton : Initial release. .LINK https://github.com/cadayton/Venom .LINK http://venom.readthedocs.io #> function Set-VeDeviceAlias { # Set-DeviceAlias Params [cmdletbinding()] Param( [Parameter(Position=0, Mandatory=$false, HelpMessage = "Enter a SAN Fabric Name", ValueFromPipeline)] [ValidateNotNullorEmpty()] [string]$FabricName = $null, [Parameter(Position=1, Mandatory=$False, HelpMessage = "Organizational owner of the SAN Fabric", ValueFromPipeline)] [ValidateNotNullorEmpty()] [string]$Org = $null, [Parameter(Position=2, Mandatory=$False, HelpMessage = "Apply Device-Alias commands for all host edge switches", ValueFromPipeline)] [ValidateNotNullorEmpty()] [switch]$apply, [Parameter(Position=3, Mandatory=$False, HelpMessage = "Enter switch name in a Fabric", ValueFromPipeline)] [ValidateNotNullorEmpty()] [string]$SwitchName = $null, [Parameter(Position=4, Mandatory=$False, HelpMessage = "Examine Current_ListLogins.csv for missing aliases", ValueFromPipeline)] [ValidateNotNullorEmpty()] [switch]$symmAlias ) # Write-Host "Set-VeDeviceAlias version 0.0.2.0" -ForegroundColor Green if (!(Get-module POSH-SSH )) { Import-Module POSH-SSH } Set-Defaults; $Script:flogiOnly = $false; if ($Script:FabricName -match "All") { # process all fabric folder Get-ChildItem $Script:SwOrgPath | ForEach-Object { # Processing flogi for each folder in <execute folder>\SWInfo-<org> $Script:FBPath = $_.PSPath; Get-ChildItem $Script:FBPath -Filter "*_Fabric_*.csv" | Where-Object { $_.Attributes -ne "Directory"} | ForEach-Object { $csvFile = $_.PSPath; Import-CSV -Path $csvFile -Header $peerHeader | Get-Flogi-Details } } } else { # Work within a specific fabric directory $Script:FBPath = $Script:SwOrgPath + "\" + $Script:FabricName; # <execute folder>\SWInfo-<org>\<fabricname> $csvFile = $Script:FBPath + "\" + $Script:FabricName + ".csv"; # <execute folder>\SWInfo-<org>\<fabricname>\<fabricname>.csv if (Test-Path $csvFile) { Import-CSV -Path $csvFile -Header $peerHeader | Get-Flogi-Details } else { # Get principal switch $switch = Get-SwitchName $Script:FabricName if ([string]::IsNullOrEmpty($switch)) { Write-Host "$Script:FabricName not found in the XMLDB" -ForegroundColor Red Write-Host "Valid Fabric names are: " -ForegroundColor Green Show-FabricNames; } else { Get-CFSPeers $switch } } } } # # |