Created
April 28, 2014 05:25
-
-
Save Mierdin/11362400 to your computer and use it in GitHub Desktop.
Two functions for automating some tedious storage-related functions with Cisco PowerTool and Netapp PowerShell Toolkit
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<# | |
Name: StorageTrueUp.ps1 | |
Author: Matthew Oswalt | |
Created: 4/27/2014 | |
Description: Storage True-Up | |
Currently only tested and verified with the following platforms: | |
Hardware Platforms: | |
*NetApp Release 8.2P2 Cluster-Mode | |
*Cisco UCSM Platform Emulator 2.2(1b)PE1 | |
*Nexus 5596UP running 6.0(2)N2(2) | |
Minimum Software Versions: | |
*Powershell 3.0 | |
*Cisco PowerTool 1.1.1.0 | |
*Netapp PowerShell Toolkit 3.0.0.90 | |
#> | |
Import-Module CiscoUcsPs | |
Import-Module DataONTAP | |
#region VARs | |
#Netapp Variables | |
$NAipAddr = "10.12.0.70" | |
$NAusername = "admin" | |
$NApassword = "Password1!" | |
$NAportset = "fcoe_pset_1" | |
$NAvserver = "VSERVER_TEST" | |
$NAbootVol = "/vol/BOOT_VOL/" #Needs to be of this format, including the forward slashes. LUN will be appended without any slashes | |
#UCS Variables | |
$UCSipAddr = "192.168.17.159" | |
$UCSusername = "config" | |
$UCSpassword = "config" | |
$UCSbootpolicy = "BFS-ESX" | |
$organization = "ORG_TEST" | |
#Place the location | |
$ConfigFile = "C:\temp\config.txt" | |
#endregion | |
#region Establish Connections | |
#Connect to Netapp, suppressing prompt | |
$NASecPass = ConvertTo-SecureString $NApassword -AsPlainText -Force | |
$NAcred = New-Object System.Management.Automation.PSCredential($NAusername, $NASecPass) | |
Connect-NcController $NAipAddr -credential $NAcred | |
#Connect to UCSM, suppressing prompt | |
$UCSSecPass = ConvertTo-SecureString $UCSpassword -AsPlainText -Force | |
$ucsmCreds = New-Object System.Management.Automation.PSCredential($UCSusername, $UCSSecPass) | |
Disconnect-Ucs | |
Connect-Ucs $UCSipAddr -Credential $ucsmCreds | |
#endregion | |
<# | |
.SYNOPSIS | |
"Trues up" the BFS configuration on a Netapp array to work with Cisco UCS. | |
.DESCRIPTION | |
Reaches into a Cisco UCS Instance, and iterates through every service profile, creating Netapp initiator groups for each one, and then putting each service profile's vHBA's WWPNs in the respective initiator groups. | |
It can run whether or not the various LUNs or IGROUPs exist - it will "true up" the configuration as necessary. | |
.EXAMPLE | |
Simply run - just run the cmdlet | |
Update-NetappCiscoBFS | |
#> | |
function Update-NetappCiscoBFS { | |
#Get SPs, not templates | |
$serviceProfiles = Get-UcsServiceProfile -Type instance -Org $organization | |
#Iterate through Service Profiles, creating boot luns and igroups, mapping as you go | |
foreach ($SP in $serviceProfiles) { | |
#create path to LUN | |
$LUNPath = $NAbootVol + $SP.name + "_boot" | |
#check to see if lun by this path already exists | |
if (Get-NcLun -path $LUNPath -Vserver $NAvserver) { | |
Write-Host "LUN already exists: " $SP.Name | |
} Else { | |
#Need to finish flushing out this line | |
New-NcLun -path $LUNPath -Size 10g -OsType vmware -Unreserved -vserver $NAvserver | |
} | |
#Populate array with existing vHBAs on this service profile | |
$vHBAs = $SP | Get-UcsVhba | |
#check to see if igroup by this name already exists | |
if (Get-NcIgroup -name $SP.Name) { | |
Write-Host "igroup already exists: " $SP.Name | |
} Else { | |
#Create the igroup first | |
Write-Host "Creating igroup named " + $SP.Name | |
$newIgroup = New-NcIgroup -name $sp.Name -protocol fcp -portset $NAportset -type VMware -vserver $NAvserver | |
#Iterate through each vHBA, and add each WWPN to this igroup | |
foreach ($vHBA in $vHBAs) { | |
Write-Host "Adding WWPN " $vHBA.Addr | |
Add-NcIgroupInitiator -Initiator $vHBA.Addr -Name $SP.Name -vserver $NAvserver | |
} | |
#Adds the mapping at the tail end. Kept inside this if statement so it only ran on igroups that were created by this script, not existing ones | |
Add-NcLunMap -Path $LUNPath -InitiatorGroup $newIgroup.Name -vserver $NAvserver | |
} | |
} | |
} | |
<# | |
.SYNOPSIS | |
Creates a Cisco NX-OS configuration snippet for zoning and aliases | |
.DESCRIPTION | |
This script will generate fibre channel configuration for NX-OS based on an existing Cisco UCS configuration. | |
Zones will be created on a one-to-many basis. | |
--Each zone will contain a single WWPN representing either the A-side or B-side vHBA of a UCS service profile. | |
--Each zone will also contain up to two additional target WWPNs, derived from the boot policy attached to the service profile. | |
--Alternatively, the "FabBWWPNs and FabBWWPNs" arguments may be supplied if you wish to bypass this feature and provide arrays containing your desired targers (i.e. if Boot-from-SAN is not being used) | |
.PARAMETER FabAVSAN | |
Provide a string array of all WWPNs on fabric A that you wish to include as targets in each zone. | |
.PARAMETER FabBWWPNs | |
Provide a string array of all WWPNs on fabric B that you wish to include as targets in each zone. | |
.PARAMETER SPfilter | |
Provide the name of a service profile template here to only include service profiles spawned from that template in the zoning configuration. | |
If you wish to include all service profiles, omit this argument. | |
.PARAMETER $FabATargets | |
A simple string array containing all WWPNs you wish to use as targets in each zone for Fabric A. This argument is optional, but if supplied, this script will not derive targets from Cisco UCS, and instead rely on this supplied array. | |
This argument is optional, but if supplied: | |
--This script will not derive targets from Cisco UCS, and instead rely on this supplied array. | |
--You must also provide the sister argument, FabBTargets. If you only supply one of these, an error will be raised when the script attempts to iterate through these. | |
.PARAMETER $FabBTargets | |
A simple string array containing all WWPNs you wish to use as targets in each zone for Fabric B. | |
This argument is optional, but if supplied: | |
--This script will not derive targets from Cisco UCS, and instead rely on this supplied array. | |
--You must also provide the sister argument, FabATargets. If you only supply one of these, an error will be raised when the script attempts to iterate through these. | |
.EXAMPLE | |
Generate configuration based on existing Boot-from-SAN policy in UCS. | |
Generate-FCSwitchConfig -FabAVSAN "10" -FabBVSAN "20" | |
.EXAMPLE | |
Generate configuration based on existing Boot-from-SAN policy in UCS, but only for service profiles that were created from the referenced service profile template | |
Generate-FCSwitchConfig -FabAVSAN "10" -FabBVSAN "20" -SPfilter "SPT-ESX" | |
.EXAMPLE | |
Generate configuration, only referencing UCS to create initiator WWPN entry. Targets derived from supplied arguments. | |
Generate-FCSwitchConfig -FabAVSAN "10" -FabBVSAN "20" -FabATargets ["50:00:00:00:00:AA:00:01", "50:00:00:00:00:AA:00:02"] -FabBTargets ["50:00:00:00:00:BB:00:01", "50:00:00:00:00:BB:00:02"] | |
#> | |
function Generate-FCSwitchConfig { | |
param( | |
[parameter(Mandatory=${true})][string]$FabAVSAN, | |
[parameter(Mandatory=${true})][string]$FabBVSAN, | |
[parameter(Mandatory=${false})][string]$SPfilter, | |
[parameter(Mandatory=${false})][string[]]$FabATargets, | |
[parameter(Mandatory=${false})][string[]]$FabBTargets | |
) | |
#Reset VSANTable dictionary back to default | |
$VSANTable = $null | |
$VSANTable = @{} | |
#This dictionary will keep our Fabric-to-VSAN mapping nice and clean. The "key" is the fabric ID, and the value is the corresponding VSAN ID. | |
$VSANTable.Add("A", $FabAVSAN) | |
$VSANTable.Add("B", $FabBVSAN) | |
#Pull down list of FcpAdapters from filer - unused right now, may use this later as a third method of deriving targets | |
#$targetAdapters = Get-NcFcpPortName -Vserver $NAvserver | |
if ($SPfilter) { | |
#If the optional $SPfilter argument was provided, use it to only retrieve service profiles created from that SP Template | |
$serviceProfiles = Get-UcsServiceProfile -Type instance -Org $organization -SrcTemplName $SPfilter | |
} else { | |
#No SPfilter argument was provided - retrieve all service profile instances | |
$serviceProfiles = Get-UcsServiceProfile -Type instance -Org $organization | |
} | |
New-Item -ItemType file $ConfigFile -Force | |
foreach ($VSANKey in $VSANTable.Keys | Sort-Object) { | |
$WWPNTable = $null | |
$WWPNTable = @{} | |
#Iterate through Service Profiles, creating boot luns and igroups, mapping as you go | |
foreach ($SP in $serviceProfiles) { | |
#Populate array with existing vHBAs on this service profile | |
$vHBAs = $SP | Get-UcsVhba | |
#Iterate through each vHBA, and add each WWPN to this igroup | |
foreach ($vHBA in $vHBAs) { | |
#Adding WWPN and name to hash table for later config generation | |
if($vHBA.SwitchId -eq $VSANKey) { | |
$WWPNTable.Add($SP.Name + "_" + $vHBA.Name, $vHBA.Addr) | |
} | |
} | |
} | |
Add-Content $ConfigFile "!Fabric $VSANKey Configuration" | |
#Create Device Alias Database configuration (matches SP+VHBA combo to WWPN) | |
Add-Content $ConfigFile "device-alias database" | |
foreach ($WWPNKey in $WWPNTable.Keys | Sort-Object) { | |
$configLine = (" device-alias name " + $WWPNKey + " pwwn " + $WWPNTable[$WWPNKey]) | |
Add-Content $ConfigFile $configLine | |
} | |
Add-Content $ConfigFile "device-alias commit" | |
Add-Content $ConfigFile "!" | |
#create zones | |
foreach ($WWPNKey in $WWPNTable.Keys | Sort-Object) { | |
Add-Content $ConfigFile ("zone name " + $WWPNKey + "_TO_NTAP vsan " + $VSANTable[$VSANKey]) | |
Add-Content $ConfigFile (" member pwwn " + $WWPNTable[$WWPNKey]) | |
#If the user decided to provide their own targets, use this info instead of pulling from UCS boot policy | |
if ($FabATargets -is [system.array] -and $FabBTargets -is [system.array]){ | |
if ($VSANKey -eq "A") { | |
foreach ($target in $FabATargets) { | |
Add-Content $ConfigFile (" member pwwn " + $target) | |
} | |
} else { | |
foreach ($target in $FabBTargets) { | |
Add-Content $ConfigFile (" member pwwn " + $target) | |
} | |
} | |
} else { #Runs if the user decided to pull targets from each service profile's boot policy. If such a policy is not connected to a service profile, this portion will fail. | |
$spname = $WWPNKey | |
$spname = $spname.substring(0, $spname.indexof('_')) #Ugly, but best way to get SP name out of SP_VHBA combo right now. May revise to keep SP and VHBA in separate params later, but right now it keeps them together nicely | |
$thisSP = Get-UcsServiceProfile -Name $spname | |
$bootpolicy = Get-UcsBootPolicy -Name $thisSP.BootPolicyName #Ugly but necessary. Don't believe there's any other way to refer to boot policy right now | |
if ($VSANKey -eq "A") { | |
$targets = $bootpolicy | Get-UcsLsbootSan | Get-UcsLsbootSanCatSanImage -Type "primary" | Get-UcsLsbootSanCatSanImagePath | |
$targets = $targets.Wwn | |
} else { | |
$targets = $bootpolicy | Get-UcsLsbootSan | Get-UcsLsbootSanCatSanImage -Type "secondary" | Get-UcsLsbootSanCatSanImagePath | |
$targets = $targets.Wwn | |
} | |
foreach ($target in $targets) { | |
Add-Content $ConfigFile (" member pwwn " + $target) | |
} | |
} | |
} | |
Add-Content $ConfigFile "!" | |
#create zoneset | |
Add-Content $ConfigFile ("zoneset name ZONESET_VSAN_" + $VSANTable[$VSANKey] + " vsan " + $VSANTable[$VSANKey]) | |
#add zones to zoneset | |
foreach ($WWPNKey in $WWPNTable.Keys | Sort-Object) { | |
Add-Content $ConfigFile (" member " + $WWPNKey) | |
} | |
Add-Content $ConfigFile "!" | |
Add-Content $ConfigFile ("zoneset activate name ZONESET_VSAN_" + $VSANTable[$VSANKey] + " vsan " + $VSANTable[$VSANKey]) | |
Add-Content $ConfigFile "!" | |
} | |
} | |
Update-NetappCiscoBFS | |
#Generate-FCSwitchConfig -FabAVSAN "10" -FabBVSAN "11" -FabATargets "50:00:00:00:00:AA:00:01", "50:00:00:00:00:AA:00:02" -FabBTargets "50:00:00:00:00:BB:00:01", "50:00:00:00:00:BB:00:02" | |
Generate-FCSwitchConfig -FabAVSAN "10" -FabBVSAN "11" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment