Microsoft Virtualization Discussions
Microsoft Virtualization Discussions
So, i'm new to the whole powershell on Netapp, but I'm looking for a way to query a bunch of filers and report on snapmirror lag time. I'm a Vbscript guy, so go easy on me as im just starting to learn powershell.
Shouldn't be difficult. You can get a flavor of this by connecting to a controller (Connect-NaController) and listing the snapmirror relationships:
PS C:\> Get-NaSnapmirror | ft -AutoSize
Source Destination Status State LagTimeTS
------ ----------- ------ ----- ---------
dunn:vol2 benson:dunn_vol2_mirror idle source 13:05:57
dunn:testvol3 benson:testvol3 idle source 188.07:48:27
benson:testvol3 dunn:testvol3 idle broken-off 188.06:48:25
dunn:AS_5_12_1 fas2050b:AS_5_12_1_NODELETE idle source 434.02:47:27
dunn:SC_3_3_0 fas2050b:SnapCreator_3_3_0_NODELETE idle source 434.02:47:00
Then it's just a matter of looping through multiple controllers and formatting the output however you want. The LagTimeTS field is a .NET TimeSpan object, so it's easy to convert that to different units.
Clinton
Thanks for the quick response.. I am a poweshell newbie, so i'm just kickin around the tires on this. I have reviewed the "getting started document and plan on reviewing your latest document "Making the most out of powershell"
The goal of the script would be to loop through a set of determined filers and anything over lets' say 50hours lag time be emailed to us. The issue is that the environment i'm thinking about is has 3800+ daily snapsmirrors and snapvaults. Right now we don't have a good way to determine where the issue is.
That sounds like a great application for a PowerShell script. You might also review a few other links that may be relevant:
https://communities.netapp.com/docs/DOC-6293
https://communities.netapp.com/docs/DOC-6196
http://www.searchmarked.com/windows/how-to-send-an-email-using-a-windows-powershell-script.php
http://blog.usepowershell.com/2009/03/how-to-send-e-mail-from-powershell/
Once you get the script working, I'd invite you to post it here in the Documents section.
Clinton,
Thanks for the linkage... Seems like I got LOTS of reading in order.. I will start to review it. If I get to the point where the script is working 100%, I will definetly post it. I will post back if i get stuck..
I've written a similar type of script and I want the LagTimeTS to be presented as actual hours:minutes:seconds and not 118.07:23:01. You wrote that "The LagTimeTS field is a .NET TimeSpan object, so it's easy to convert that to different units." I've done a bit of googeling, but I can't figure out how I can convert it. I'm new to powershell, so some pointers to how to do this would be really nice.
fmc - you want to share what you already have?
Sure... I'm not very good at powershell, but this works for me. Although there are probably better ways of doing it.
We got multiple filers with different user/pass so I made one of these for each filer. I don't know ho to use the foreach cmdlet when I have to deal with multiple filers, user and password.
# Import the proper powershell module
Import-module DataONTAP.psd1
# Set your alert time here, this is in seconds. Lagtime higher than 24 hrs
$LagTimeSeconds = "86400"
# Set your root password
$filerpassw = "p@ssword"
Set your Filer IP or FQDN
$filername1 = "netapp.example.com"
#SMTP server
$PSEmailServer = "smtp.example.com"
#Mail body array
$body = @()
################# FILER1 #################
# Create an encrypted string which the API will use — Change password below
$password = ConvertTo-SecureString $filerpassw -AsPlainText –Force
# Create a credential object in powershell against the root user – Change root user if you use a different admin user
$cred = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList "root",$password
# Connect to the Filer using the credential created above – You can change the FQDN or IP below
$connection = Connect-NaController $filername1 -Credential $cred
$body += Get-NaSnapmirror | where-object {$_.LagTime -gt $LagTimeSeconds}
$body = $body | out-string
send-mailmessage -to "User01 <user1@example.com>" -from "User02 <user2@example.com>" -subject "Snapmirror status" -body "$body"
Yeah, i'm just getting rockin with it as well.. I will kick the tires on your script as well.
"118.07:23:01" is days.hours:minutes:seconds, which isn't much different.
You can use the various TimeSpan properties to get whatever you want:
PS C:\> $ts = (Get-NaSnapmirror -Location dunn:AS_5_12_1).LagTimeTS
PS C:\> $ts
Days : 450
Hours : 20
Minutes : 26
Seconds : 29
Milliseconds : 0
Ticks : 389535890000000
TotalDays : 450.851724537037
TotalHours : 10820.4413888889
TotalMinutes : 649226.483333333
TotalSeconds : 38953589
TotalMilliseconds : 38953589000
PS C:\> $ts.ToString()
450.20:26:29
PS C:\> ([int] $ts.TotalHours).ToString() + ":" + $ts.Minutes + ":" + $ts.Seconds
10820:26:29
http://msdn.microsoft.com/en-us/library/system.timespan.aspx
Just thought I'd add a pedantic note about PowerShell's weird integer rounding rules. You might want to use [Math]::Truncate() in this case to make sure you don't accidentally round up an extra hour:
PS C:\> [Math]::Truncate($ts.TotalHours).ToString() + ":" + $ts.Minutes + ":" + $ts.Seconds
10820:26:29
It would be cool if i knew a way to convert 3.05:14:59 to days, hours, minutes, seconds. So, like 3days,5hours,15minutes,59seconds Is that a powershell expression that needs to happen?
Trivial:
PS C:\> $ts
Days : 450
Hours : 20
Minutes : 26
Seconds : 29
Milliseconds : 0
Ticks : 389535890000000
TotalDays : 450.851724537037
TotalHours : 10820.4413888889
TotalMinutes : 649226.483333333
TotalSeconds : 38953589
TotalMilliseconds : 38953589000
PS C:\> [String]::Format("{0} days, {1} hours, {2} minutes, {3} seconds", $ts.days, $ts.Hours, $ts.Minutes, $ts.Seconds)
450 days, 20 hours, 26 minutes, 29 seconds
Clinton,
Now i'm sort of getting somewhere
I took your advice from the other thread and have come up with this
"
gc $hostfile | % { $c = Connect-NaController -credential $cred $_; Write-Host "`nController: $c`n"; Get-NaSnapmirror | where-object {$_.LagTime -gt $LagTimeSeconds} }
"
A few things i'm noticing. As the script loops through it strips out the headers on each loop. so for the first example it only lists
Controller: filera
Source Destination Status State LagTimeTS
------ ----------- ------ ----- ---------
Also, what is the best way to write the host name like we are and then if it doesn't meet the criteria to write "no snapmirror lag issue"
I was thinking along the lines of
$lag = Get-NaSnapmirror | where-object {$_.LagTime -gt $LagTimeSeconds
Am i totally off base?
I'm also noticing the built in formatting is not big enough for some of our volume names. I am going to work on that with the expression statements like you did in the other post. I will re-post when im done.
Clinton,
Got my heads back with the following code.. I took your advince from the previous thread.. Still needs work but it's a start
$lagtimeseconds = "86400"
gc $hostfile | % {
$c = Connect-NaController $_ -credential $cred
Get-NaSnapmirror | where-object {$_.LagTime -gt $LagTimeSeconds} | Select SourceLocation,DestinationLocation,Status,State,LagtimeTS | ft @{expression={$c};Label="Filer name";width=20},@{expression={$_.SourceLocation};Label="Source";Width=40},@{Expression={$_.DestinationLocation};Label="Destination";Width=40},@{expression={$_.status};Label="status";width=20},@{Expression={$_.state};Label="state";width=20},@{Expression={$_.lagtimets};label="lag time";width=20}
}
I had to increase the widths b/c our volume are quite long. I'm not a true fan of how i did filer name, but it's a start.
I would more like
*** Filer Name ****
blah blah
That's for tomorrow.. And then i will do the same for snapvault status.. This will really helps us out. I knew you converted lagtimTS into days and hours. I'm thinking how I would do this in VB. I would create a function that does that that I can whip a variable through to convert. is it something similiar?
Josh, you're on the right track. Try the -GroupBy parameter to Format-Table. That can save you a little horizontal space. 'Fraid I can't help you with VB, though!
PS C:\> gc .\filers.txt | % { $c = Connect-NaController $_; Get-NaSnapmirror | where-object {$_.LagTime -gt $LagTimeSeconds} | Select SourceLocation,DestinationLocation,Status,State,LagtimeTS | ft @{expression={$_.SourceLocation};Label="Source";Width=40},@{Expression={$_.DestinationLocation};Label="Destination";Width=40},@{expression={$_.status};Label="status";width=20},@{Expression={$_.state};Label="state";width=20},@{Expression={$_.lagtimets};label="lag time";width=20} -GroupBy @{expression={$c};Label="Filer name"} }
Filer name: dunn
Source Destination status state lag time
------ ----------- ------ ----- --------
dunn:testvol3 benson:testvol3 idle source 209.08:02:47
benson:testvol3 dunn:testvol3 idle broken-off 209.07:02:45
dunn:AS_5_12_1 fas2050b:AS_5_12_1_NODELETE idle source 455.03:01:47
dunn:SC_3_3_0 fas2050b:SnapCreator_3_3_0_NODELETE idle source 455.03:01:20
Filer name: benson
Source Destination status state lag time
------ ----------- ------ ----- --------
dunn:testvol3 benson:testvol3 idle broken-off 209.08:02:48
benson:testvol3 dunn:testvol3 idle source 209.07:02:46
Clinton,
Here's what I have so far.. There are a few flaws that I want to work on. I would rather not put the password stored in the script. I can compile it, but i was wondering if there is a better way to do this
Also, i had to abandon the Format-table command b/c I couldn't figure out how to format-table and then dump to csv. Also, the way we are dumping to CSV is kind of lame. I would like to use native Excel API, but i know this is a lot more challenging and i'm not sure i'm ready for it. But basically this gets the job done for now. It's ugly but it works.
Improvements, comments, suggestions are welcome and appreciated.
### Mail "constants"
$sendMailAs = "xx"
$recipients = "x
$subjectLine = "Daily Exchange VSM LAG TIME"
$mailMessage = "Daily Exchange VSM Lag time"
$smtpServer = "x"
$priority = "high"
### File Constants
$date = (get-date).toString('dd-MMM-yyyy_h-mm-ss')
$ext = ".xls"
$outfile = "Exchange_VSM_Lag_" + $date + $ext
$delim = "`t"
### Import Data OnTap Module
# Check toolkit version
try
{
if (-Not (Get-Module DataONTAP))
{
Import-Module DataONTAP -EA 'STOP' -Verbose:$false
}
if ((Get-NaToolkitVersion).CompareTo([system.version]'1.7') -LT 0) { throw }
}
catch [Exception]
{
Write-Warning "This script requires Data ONTAP PowerShell Toolkit 1.7 or higher."
return;
}
### Define Lag time
$lagtimeseconds = "86400" #24 hour lagtime
### Input File properties
$hostfile = "hosts.txt"
$accnt = "xx"
$filerpassw = "xxx"
$password = ConvertTo-SecureString $filerpassw -AsPlainText –Force
$cred = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $accnt,$password
$snapMirrors = @()
gc $hostfile | % {
$C = Connect-NaController -credential $cred $_
$snapMirrors += Get-NaSnapmirror | where-object {$_.lagTime -gt $lagTimeSeconds} | Select SourceLocation,DestinationLocation,Status,State,LagtimeTS # | ft @{expression={$c};Label="Filer name";width=20},@{expression={$_.SourceLocation};Label="Source";Width=40},@{Expression={$_.DestinationLocation};Label="Destination";Width=40},@{expression={$_.status};Label="status";width=20},@{Expression={$_.state};Label="state";width=20},@{Expression={$_.lagtimets};label="lag time";width=20}
}
$dataToWrite = $snapMirrors | convertTo-Csv -delimiter $delim -noType
$dataToWrite | sc $outfile
## Send Email
Send-MailMessage -To $recipients -From $sendMailAs -Attachments $outfile -Subject $subjectLine -Body $mailMessage -Priority $priority -SmtpServer $smtpServer
#####
I forgot to mention that i keep getting this trailing errror. I made sure the input file had no trailing spaces and I can't figure out where it's coming from.. a bit of annoying
ERROR: ConvertTo-Csv : Cannot bind argument to parameter 'InputObject' because it is null.
ERROR: At C:\temp\good\good\lagtime2.ps1:68 char:44
ERROR: + $dataToWrite = $snapMirrors | convertTo-Csv <<<< -delimiter $delim -noType
ERROR: + CategoryInfo : InvalidData: (:) [ConvertTo-Csv], ParameterBindingValidationException
ERROR: + FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.ConvertToCsvCommand
ERROR:
Hi Josh,
I'd recommend "Add-NaCredential -SystemScope" for managing the creds. Simply connect to your controller at the console and then call that cmdlet. Then in your script, don't specify credentials at all, and the machine encrypted values you entered earlier will be used automatically!
You shouldn't be using FT/Format-Table to send data to CSV. Format-Table is really for sending data to the screen/console. Instead, just use "Select-Command" like you are doing which builds PSObjects. Note that you can pass expressions like "@{Name=SomeField;Expression={$Some[Value]}}" to the select cmdlet.
The Exception you mention is probably from a controller with no out-of-date mirrors. In that case PowerShell is going to push a $null onto your $snapMirrors list. You can easily filter those out like this:
$snapMirrors | where {$_} | convertTo-Csv -delimiter $delim -noType
Cheers!
Eric
Eric,
Thanks for the points, I will review the add-nacredential cmdlet. I still don't understand how that will work in an automated script job.. It can't prompt me for passwords. Will review this weekend.
I will check out adjusting thta line to handle any Null values..
More to come next week.
Josh, Add-NaCredential securely stores controller credentials in a local cache file. If you don't explicitly provide credentials or specify -RPC, Connect-NaController consults the cache and uses any credentials found there. So it's a great way to keep from having to prompt for credentials in an automated script job. Like Eric said, if your automated job runs in a Windows user context other than your own, use "Add-NaCredential -SystemScope" to ensure other authenticated users on the local host can access the credentials store.