Just over a week since releasing Version 1, I decided to rewrite the core functions, obey PowerShell’s verb naming
conventions, and re-release with more functions as Version 2!
Save the script as McCmdlets.psm1
into C:\Users\{USERNAME}\Documents\WindowsPowerShell\Modules\McCmdlets
and import into PowerShell with>
Import-Module
McCmdlets.psm1
Note: Where cDOT
cmdlets have Nc in the name, since these cmdlets are designed for managing
multiple clusters, hence Mc, and with a plural in the names (not the singular.)
There is built in help>
Get-McHelp
The McCmdlets
So Far:
Get-McVservers
Get-McVserversAdmin
- Get all Admin
SVMs for all clusters...
Get-McVserversRunningData
- Get all Running
Data SVMs for all clusters...
Get-McVolsTypeAndState
- Get Type and
State of all volumes for all clusters...
Get-McVolsOffline
- Get all offline
volumes for all clusters...
Get-McVolsRwOnline
- Get all R/W
online volumes for all clusters...
Remove-McVolsOffline
- Remove all
offline volumes in all Running Data SVMs...
Set-McUsersPasswordForAdminSVM
- Set a user’s
password across all Admin SVMs...
Remove-Mc7modeSnapshots
- Remove 7-Mode
Snapshots from all R/W online volumes in all Running Data SVMs...
Get-McLunsMappedStatus
- Get LUNs mapped
status for all Running Data SVMs...
Get-McVolsWithLuns
- Get all volumes
with LUNs for all Running Data SVMs...
Get-McVolsWithMappedLuns
- Get all volumes
with Mapped LUNs for all Running Data SVMs...
Get-McVolsWithOnlyUnmappedLuns
- Get all volumes
with only UnMapped LUNs for all Running Data SVMs...
Set-McVolsWithOnlyUnmappedLunsOffline
- Set all volumes
with only UnMapped LUNs offline for all Running Data SVMs...
The Code
############################
##
PART 1: McCmdlets Core ##
############################
Function
Get-McHelp{
Wr;Wr "+++++ Multi-cluster Cmdlets
(McCmdlets) +++++" MAGENTA; Wr
Wr;Wr "A selection of cmdlets to manage
multiple clusters in one go!" CYAN; Wr
Wr;Wr "1 " CYAN; Wr
'Import-McClusters (creates Global variable $McClusterNames)' GREEN
If($Global:McClusterNames){ $Color =
"GREEN" }
else{ Wr;Wr;Wr " ===== Run Import-McClusters ==== " RED;
Wr; $Color = "RED" }
Wr;Wr "2 " CYAN; Wr
"Add-McCredentials" $Color
Wr;Wr "- " CYAN; Wr
"Remove-McCredentials" $Color
If(!$Global:McClusterNames){}
elseif(Get-McCredentials){ $Color =
"GREEN" }
else{ Wr;Wr;Wr " ===== Run Add-McCredentials ==== " RED;
Wr; $Color = "RED" }
Wr;Wr "3 " CYAN; Wr
'Connect-McControllers (creates Global variable $McConnectedClusters)' $Color
Wr;Wr "- " CYAN; Wr
"Clear-McControllers" $Color; Wr
Wr;Wr 'Run 1 -> 2 -> 3, then we are
ready to use the below McCmdlets against $McConnectedClusters!' CYAN; Wr
If($Global:McConnectedClusters){ $Color =
"GREEN" }
elseif($Global:CurrentNcController){ Wr 'No
$McConnectedClusters, run Connect-McControllers, otherwise the below will run
against the $CurrentNcController(s)!' YELLOW; Wr; $Color = "YELLOW" }
else{ Wr 'No $McConnectedClusters and no
$CurrentNcController!' RED; Wr; $Color = "RED" }
Wr;Wr "
Get-McVservers" $Color
Wr;Wr "
Get-McVserversAdmin" $Color
Wr;Wr "
Get-McVserversRunningData" $Color
Wr;Wr "
Get-McVolsTypeAndState" $Color
Wr;Wr "
Get-McVolsOffline" $Color
Wr;Wr "
Get-McVolsRwOnline" $Color
Wr;Wr "
Remove-McVolsOffline" $Color
Wr;Wr "
Set-McUsersPasswordForAdminSVM" $Color
Wr;Wr "
Remove-Mc7modeSnapshots" $Color
Wr;Wr "
Get-McLunsMappedStatus" $Color
Wr;Wr "
Get-McVolsWithLuns" $Color
Wr;Wr "
Get-McVolsWithMappedLuns" $Color
Wr;Wr "
Get-McVolsWithOnlyUnmappedLuns" $Color
Wr;Wr "
Set-McVolsWithOnlyUnmappedLunsOffline" $Color
Wr;Wr
}
Function
Get-McCredentials{
[Void](Get-DataOntapPSTK)
If(!$Global:McClusterNames){ RETURN $FALSE }
Foreach($Cluster in $Global:McClusterNames){
If(!(Get-NcCredential -Name $Cluster)){ RETURN $FALSE } }
RETURN $TRUE
}
Function
Get-DataOntapPSTK{
If(!(Get-Module DataONTAP)){
[Void](Import-Module DataONTAP -ErrorAction SilentlyContinue) }
If(!(Get-Module DataONTAP)){ RETURN $FALSE }
else { RETURN $TRUE }
}
Function
Import-McClusters {
Param([String]$File)
If(Get-DataOntapPSTK){ Wr; Wr "PSTK
loaded ..." GREEN; Wr }
else{ Wr; Wr "Unable to load PSTK!"
RED; Wr; Wr; RETURN }
Wr; Wr "Loading file containing cluster
management IPs/Name ..." CYAN; Wr; Wr
[String]$File = Get-Prompt -Prompt
"Enter Filename/Filepath" -PreAnswer $File
If(Test-Path $File){
[System.Array]$FileContent = Get-Content $File }
Else{ Wr; Wr "Failed to load
$File!" RED; Wr; Wr; RETURN }
If($FileContent.count -eq 0){ Wr; Wr "No
content in $File!" RED; Wr; Wr; RETURN }
[System.Array]$Global:McClusterNames = @()
$FileContent = $FileContent | Where {
($_.Trim("`t"," ") -ne "") -and
!$_.StartsWith("#") }
$FileContent | Foreach {
$Global:McClusterNames += $_.Split("#")[0].Trim("`t","
") }
If($Global:McClusterNames.count -eq 0){ Wr;
Wr "No valid content in $File!" RED; Wr; Wr; RETURN }
Wr; Wr "Loaded $File ..." GREEN; Wr
Wr; Wr 'PS> $McClusterNames' CYAN; Wr; Wr
$Global:McClusterNames; Wr
}
Function
Add-McCredentials{
Param([Switch]$Remove)
[System.Array]$Global:McConnectedClusters =
@()
If(!$Global:McClusterNames){ Wr; Wr 'No
$McClusterNames - run Import-McClusters!' RED; Wr; Wr; RETURN }
If(!$Remove){ Wr; Wr 'Note: If there are
existing stored NcCredentials for $McClusterNames, they will be overwritten
(can use Get-NcCredential to check)!' YELLOW; Wr; Wr }
If(!$Remove){ [String]$UserName = Get-Prompt
-Prompt "Enter Username" }
If(!$Remove){ Wr "Enter Password:"
CYAN; $Password = Read-Host -AsSecureString }
If(!$Remove){ $Credentials = New-Object
System.Management.Automation.PsCredential($Username,$Password) }
If(!$Remove){ $Global:McClusterNames |
Foreach{ [Void](Add-NcCredential -Controller $_ -Credential $Credentials) } }
else{ $Global:McClusterNames | Foreach{
[Void](Remove-NcCredential -Name $_ -ErrorAction SilentlyContinue) } }
Wr; Wr 'PS> (Get-NcCredential).Name |
Where{ $Global:McClusterNames -Contains $_ }' CYAN; Wr; Wr
(Get-NcCredential).Name | Where{ $Global:McClusterNames
-Contains $_ }; Wr
}
Function
Remove-McCredentials{ [Void](Add-McCredentials -Remove) }
Function
Connect-McControllers{
If(!(Get-McCredentials)){ Wr; Wr 'Unable to
get credentials for Clusters, have your run Import-McClusters and Add-McCredentials?'
RED; Wr; Wr; RETURN }
[System.Array]$Global:McConnectedClusters =
@(); Wr
$Global:McClusterNames | Foreach {
$Connected = Connect-NcController -Name $_
-Timeout 15000 -ErrorAction SilentlyContinue
If($Connected){ $Global:McConnectedClusters
+= $_; Wr "Connected to $_!" GREEN; Wr }
Else{ Wr "Unable to connect to
$_!" RED; Wr }
}
$Global:CurrentNcController = $null
$Global:McConnectedClusters | Foreach {
[Void](Connect-NcController -Name $_ -Add -Timeout 15000 -ErrorAction SilentlyContinue)
}
Wr; Wr 'Connected to the $McConnectedClusters
below:' GREEN; Wr
Wr 'PS> $CurrentNcController | FT
Name,Address,Vserver,Version -AutoSize' CYAN; Wr
$Global:CurrentNcController | FT
Name,Address,Vserver,Version -AutoSize
}
Function
Clear-McControllers{
[System.Array]$Global:McConnectedClusters =
@()
$Global:CurrentNcController = $null
}
Function
Wr{
Param([String]$Echo,[String]$Ink =
"WHITE")
If($Echo){ Write-Host $Echo -ForegroundColor
$Ink -NoNewLine }else{ Write-Host }
}
Function
Get-Prompt{
Param([String]$Prompt,[System.Array]$Answers,[String]$PreAnswer,[Switch]$CaseSensitive,[Switch]$AllowCR)
While ($true){
Wr ($Prompt + ":") CYAN
If($PreAnswer){ Wr $PreAnswer; Wr; RETURN
$PreAnswer }else{ $ReadIn = Read-Host }
If($Answers -and $CaseSensitive){ Foreach ($a in $Answers){
If($ReadIn -ceq $a){ RETURN $ReadIn } } }
If($Answers -and !$CaseSensitive){ Foreach
($a in $Answers){ If($ReadIn -eq $a){
RETURN $ReadIn } } }
If(!$Answers -and ($ReadIn.length -gt 0) ){
RETURN $ReadIn }
If($AllowCR
-and ($ReadIn.length -eq 0) ){ RETURN "" }
}
}
###############################
##
PART 2: McCmdlets Cmdlets ##
###############################
##
===== McVservers SECTION ===== ##
Function
Get-McVservers {
Param([System.Object]$NcController,[Switch]$Admin,[Switch]$RunningData,[Switch]$NoFormat)
If(!$Global:CurrentNcController){ RETURN }
# ===== SVM ATTRIBUTES ===== #
$VsAttrs = Get-NcVserver -Template
$VsAttrs.Comment = ""
$VsAttrs.OperationalState = ""
$VsAttrs.VserverType = ""
# ===== ACQUIRE DATA ===== #
If(!$NcController){ [System.Object]$SVMs =
Get-NcVserver -Attributes $VsAttrs }
else{ [System.Object]$SVMs =
Get-NcVserver -Controller $NcController -Attributes $VsAttrs }
# ===== FUNCTION OUTPUT ===== #
If($Admin){ $SVMs = $SVMs | Where{
$_.VserverType -eq "admin" } }
elseif($RunningData){ $SVMs = $SVMs | Where{
($_.OperationalState -eq "running") -and ($_.VserverType -eq
"data") } }
[System.Array]$TableFormat = @()
$TableFormat +=
@{label='Cluster';e={$_.NcController.Name}}
$TableFormat +=
@{label='Vserver';e={$_.VserverName}}
$TableFormat +=
@{label='State';e={$_.OperationalState}}
$TableFormat += @{label='Type';e={$_.VserverType}}
$TableFormat += "Comment"
If($NoFormat){ $SVMs }
else{ $SVMs | FT $TableFormat -AutoSize }
}
Function
Get-McVserversAdmin{ Get-McVservers -Admin }
Function
Get-McVserversRunningData{ Get-McVservers -RunningData }
##
====== McVols SECTION ===== ##
Function
Get-McVolsTypeAndState {
Param([System.Object]$NcController,[String]$Vserver,[Switch]$Offline,[Switch]$RwOnline,[Switch]$NoFormat)
If(!$Global:CurrentNcController){ RETURN }
# ===== VOLUME ATTRIBUTES ===== #
$VolAttrs = Get-NcVol -Template
Initialize-NcObjectProperty -Object $VolAttrs
-Name VolumeIdAttributes
Initialize-NcObjectProperty -Object $VolAttrs
-Name VolumeStateAttributes
$VolAttrs.VolumeIdAttributes.Comment = ""
$VolAttrs.VolumeIdAttributes.Type = ""
$VolAttrs.VolumeStateAttributes.State =
""
# ===== ACQUIRE DATA ===== #
If(!$NcController){ [System.Object]$Vols =
Get-NcVol -Attributes $VolAttrs }
elseif(!$Vserver){ [System.Object]$Vols = Get-NcVol -Controller
$NcController -Attributes $VolAttrs }
else{ [System.Object]$Vols = Get-NcVol
-Controller $NcController -VserverContext $Vserver -Attributes $VolAttrs }
# ===== FUNCTION OUTPUT ===== #
If($Offline){ $Vols = $Vols | Where{
$_.VolumeStateAttributes.State -eq "offline" } }
elseif($RwOnline){ $Vols = $Vols | Where{
($_.VolumeIdAttributes.Type -eq "rw") -and
($_.VolumeStateAttributes.State -eq "online") } }
[System.Array]$TableFormat = @()
$TableFormat += @{label='Cluster';e={$_.NcController.Name}}
$TableFormat += "Vserver"
$TableFormat += "Name"
$TableFormat +=
@{label='Type';e={$_.VolumeIdAttributes.Type}}
$TableFormat +=
@{label='State';e={$_.VolumeStateAttributes.State}}
$TableFormat +=
@{label='Comment';e={$_.VolumeIdAttributes.Comment}}
If($NoFormat){ $Vols }
else{ $Vols | FT $TableFormat -AutoSize }
}
Function
Get-McVolsOffline{
Get-McVolsTypeAndState -Offline }
Function
Get-McVolsRwOnline{ Get-McVolsTypeAndState -RwOnline }
Function
Remove-McVolsOffline{
Param([String]$OverrideFile,[Switch]$NoPrompt)
# ===== HANDLE THE OVERRIDE FILE ===== #
[System.Array]$Overrides = @()
If($OverrideFile -and (Test-Path
$OverrideFile)){
[System.Array]$FileContent = Get-Content
$OverrideFile
$FileContent = $FileContent | Where {
($_.Trim("`t"," ") -ne "") -and
!$_.StartsWith("#") }
$FileContent | Foreach { $Overrides +=
$_.Split("#")[0].Trim("`t"," ") }
}elseif($OverrideFile){ Wr;Wr "Failed to
load specified override file $OverrideFile!" RED;Wr;Wr;RETURN }
# ===== REMOVE OFFLINES VOLUMES NOT IN OVERRIDES
===== #
$Global:CurrentNcController | Foreach {
Foreach($SVM in (Get-McVservers $_
-RunningData -NoFormat) ){
Foreach($Volume in
(Get-McVolsTypeAndState $_ $SVM.VserverName -Offline -NoFormat) ){
If($Overrides -NotContains $Volume.Name){
If(!$NoPrompt){ $Volume |
Remove-NcVol }
Else{ $Volume | Remove-NcVol
-Confirm:$FALSE }
}
}
}
}
}
##
===== McUsers SECTION ===== ##
Function
Set-McUsersPasswordForAdminSVM{
If(!$Global:CurrentNcController){ RETURN };
Wr
[String]$UserName = Get-Prompt -Prompt
"Enter user whose password is to be reset"
Wr "Enter new password:" CYAN;
$Password = Read-Host -AsSecureString
$NewCred = New-Object
System.Management.Automation.PsCredential($UserName,$Password); Wr
$Global:CurrentNcController | Foreach {
$Vserver = (Get-McVservers $_ -Admin
-NoFormat).VserverName
[System.Array]$GetUser = Get-NcUser -Name
$UserName -Vserver $Vserver -Controller $_ -ErrorAction SilentlyContinue
If(!$GetUser){ Wr ("User $UserName
does not exist on " + $_.Name + ":" + $Vserver + "!")
RED; Wr }
elseif($GetUser[0].AuthMethod -ne
"password"){ Wr ("User $UserName is not password authenticated
on " + $_.Name + ":" + $Vserver + "!") RED; Wr }
else{
[Void](Set-NcUserPassword -Credential
$NewCred -VserverContext $Vserver -Controller $_)
Wr ("Ran Set-NcUserPassword for user
$UserName on " + $_.Name + ":" + $Vserver + "!")
GREEN; Wr
}
}; Wr
}
##
===== Mc7modeSnapshots SECTION ===== ##
Function
Remove-Mc7modeSnapshots{
If( !$Global:CurrentNcController){ RETURN };
Wr
$SnapAttrs = Get-NcSnapshot -Template
$SnapAttrs.Is7ModeSnapshot = ""
$Global:CurrentNcController | Foreach {
Foreach($SVM in (Get-McVservers $_
-RunningData -NoFormat) ){
Foreach($Volume in
(Get-McVolsTypeAndState $_ $SVM.VserverName -RwOnline -NoFormat) ){
Wr ("Removing any 7-Mode snapshots
from " + $_.Name + ":" + $SVM.VserverName + "\" + $Volume.Name)
YELLOW; Wr
$SevenModeSnapshots = Get-NcSnapshot
-Volume $Volume.Name -Attributes $SnapAttrs -Controller $_ -Vserver
$SVM.VserverName | Where { $_.Is7ModeSnapshot -eq $TRUE }
$SevenModeSnapshots | Format-Table
Name,Is7ModeSnapshot -AutoSize
$SevenModeSnapshots | Where {
$_.Is7ModeSnapshot -eq $TRUE } | Remove-NcSnapshot -Confirm:$FALSE
}
}
};Wr
}
##
===== McLuns SECTION ===== ##
Function
Get-McLunsMappedStatus{
Param([Switch]$NoFormat)
If(!$Global:CurrentNcController){ RETURN }
$LunAttrs = Get-NcLun -Template
$LunAttrs.Mapped = ""
[System.array]$LunArray = @()
$Global:CurrentNcController | Foreach {
Foreach($SVM in (Get-McVservers $_
-RunningData -NoFormat) ){
Foreach($Volume in (Get-McVolsTypeAndState
$_ $SVM.VserverName -RwOnline -NoFormat) ){
$LUNs = Get-NcLun -Volume $Volume.Name
-Attributes $Attrs -VserverContext $SVM.VserverName -Controller $_
Foreach($LUN in $LUNs){ $LunArray +=
$LUN }
}
}
}
If($NoFormat){ $LunArray }
else{ $LunArray | FT
@{label='Cluster';e={$_.NcController.Name}},Vserver,Mapped,Volume,Path
-AutoSize }
}
Function
Get-McVolsWithLuns{
Param([Switch]$VolsWithMappedLuns)
[System.Array]$ObjectCollection = @()
If($VolsWithMappedLuns){ $GetMcLuns =
Get-McLunsMappedStatus -NoFormat | Where { $_.Mapped -eq $TRUE } }
else{ $GetMcLuns = Get-McLunsMappedStatus
-NoFormat }
$GetMcLuns | Foreach{
$Object = New-Object PSObject
Add-Member -InputObject $Object -MemberType
NoteProperty -Name Cluster -Value ($_.NcController.Name)
Add-Member -InputObject $Object -MemberType
NoteProperty -Name Vserver -Value ($_.Vserver)
Add-Member -InputObject $Object -MemberType
NoteProperty -Name Volume -Value
($_.Volume)
If( !($ObjectCollection -Match $Object) ){
$ObjectCollection += $Object }
}
$ObjectCollection
}
Function
Get-McVolsWithMappedLuns{ Get-McVolsWithLuns -VolsWithMappedLuns }
Function
Get-McVolsWithOnlyUnmappedLuns{
$VolsWithMappedLuns = Get-McVolsWithMappedLuns
[System.Array]$ObjectCollection = @()
Get-McVolsWithLuns | Foreach{
If( !($VolsWithMappedLuns -Match $_) ){
$ObjectCollection += $_ }
}
$ObjectCollection
}
Function
Set-McVolsWithOnlyUnmappedLunsOffline{
Foreach($Vol in Get-McVolsWithOnlyUnmappedLuns){
$Controller = $Global:CurrentNcController |
Where{ $_.Name -eq $Vol.Cluster }
Set-NcVol -Offline -Name $Vol.Volume
-VserverContext $Vol.Vserver -Controller $Controller
}
}
Comments
Post a Comment