Skip to content

Instantly share code, notes, and snippets.

@Mierdin
Created April 28, 2014 05:25
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Mierdin/11362400 to your computer and use it in GitHub Desktop.
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
<#
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