{"id":500,"date":"2010-01-25T16:17:07","date_gmt":"2010-01-25T21:17:07","guid":{"rendered":"http:\/\/www.jasemccarty.com\/blog\/?p=500"},"modified":"2010-01-25T16:17:07","modified_gmt":"2010-01-25T21:17:07","slug":"netapp-snapmirror-monitor-script-part-1","status":"publish","type":"post","link":"https:\/\/www.jasemccarty.com\/blog\/netapp-snapmirror-monitor-script-part-1\/","title":{"rendered":"NetApp SnapMirror Monitor Script &#8211; Part 1"},"content":{"rendered":"<p>When I designed a DR solution a while back, I knew what I needed to do, what the software\/hardware involved would do, but wasn&#8217;t sure about a couple things, including how to monitor it.<\/p>\n<p>I did a Google search on <strong><a title=\"http:\/\/www.google.com\/search?hl=en&amp;num=100&amp;newwindow=1&amp;q=NetApp+SnapMirror+Monitoring&amp;aq=f&amp;aql=&amp;aqi=&amp;oq=\" href=\"http:\/\/www.google.com\/search?hl=en&amp;num=100&amp;newwindow=1&amp;q=NetApp+SnapMirror+Monitoring&amp;aq=f&amp;aql=&amp;aqi=&amp;oq=\" target=\"_blank\">NetApp SnapMirror Monitoring<\/a><\/strong>, and didn&#8217;t find much, given the route I chose to take, a Windows system running <strong>Snap Manager for Virtual Infrastructure (SMVI)<\/strong>.  I chose to have this system report the SnapMirror status.<\/p>\n<p>It didn&#8217;t make sense to me to use a Linux\/Unix system to handle this role (as I don&#8217;t have many of these systems).  It did make sense to me to have my system running SMVI to perform the task.<\/p>\n<p>I started by using <strong><a title=\"http:\/\/www.chiark.greenend.org.uk\/~sgtatham\/putty\/download.html\" href=\"http:\/\/www.chiark.greenend.org.uk\/~sgtatham\/putty\/download.html\" target=\"_blank\">plink.exe<\/a><\/strong> to execute the <strong>&#8220;snapmirror status&#8221;<\/strong> command on my remote Filer.  I like plink, because it can execute a ssh command remotely, and can be scripted.<\/p>\n<p>To make plink.exe execute a remote snapmirror status command, the syntax would be something like this:<\/p>\n<blockquote><p><strong>plink user@filername_or_ip -pw password &#8220;snapmirror status&#8221;<\/strong><\/p><\/blockquote>\n<p>I will admit, it isn&#8217;t the best method to use a clear password in a script.  I don&#8217;t.  I generated an ssh key and included it in my authorized_keys on my target Filer.  I&#8217;m not going to go into that process in this post.<\/p>\n<p>Now, the next step, is to be able to grab the information that the target filer responds with.  This information would look something like this:<\/p>\n<blockquote><p><strong>Snapmirror is on.<br \/>\nSource                                    Destination                           State          Lag        Status<br \/>\nsourcefiler:\/vol\/nfs_volume\/nfs_volume  destfiler:\/vol\/nfs_volume_dr\/nfs_volume  Snapmirrored   02:09:16   Idle<\/strong><\/p><\/blockquote>\n<p>Let me go into a little detail on the way the volumes are configured.  On both Filers, there is a volume presented as NFS to ESX named <strong>nfs_volume<\/strong>.  Also, there is a qtree named <strong>nfs_volume<\/strong> <em>within <\/em>the volume (nfs_volume).<\/p>\n<p><strong>Confusing?  A little bit.<\/strong><br \/>\nThe reason I created qtrees with the same name, is because I&#8217;m doing SnapMirror replication at the qtree level, and not at the volume level.  This is because to successfully replicate from volume to volume, the two Filers have to be running the same version of ONTAP.  I cannot always be sure that both Filers will be at the same version (or revision), so I decided to replicate at the qtree level.  Replication of qtrees does not require the Filers to be on the same version of ONTAP.<\/p>\n<p><strong>The hard part<\/strong><br \/>\nPlink very easily returns data back from a command line.  That is unless you want to pipe that to a file.  And when you grab that information, how do you get it in a tangible medium.<\/p>\n<p><strong>My first script<\/strong><br \/>\nHere is a copy of my first script.  It is pretty rudimentary, but it was a start.<\/p>\n<blockquote><p>&#8216;*************************************************<br \/>\n&#8216;* NetApp SnapMirror Monitoring Script version 0.1<br \/>\n&#8216;* October 2009<br \/>\n&#8216;* Jase McCarty<br \/>\n&#8216;*************************************************<\/p>\n<p>&#8216;Set our output file<br \/>\noutFile = &#8220;C:pathplinkout.TXT&#8221;<br \/>\n&#8216;Set our Mail Server&#8217;s DNS Name<br \/>\nSMTPServer = &#8220;mail.domain.com&#8221;<\/p>\n<p>&#8216;Setup a Wscript Shell Object so we can execute a command line instruction<br \/>\nset objShell = wscript.createObject(&#8220;wscript.shell&#8221;)<\/p>\n<p>&#8216;Run the command<br \/>\niReturn = objShell.Run(&#8220;CMD \/C plink.exe user@netapp.domain.com -pw password &#8221; &amp; CHR(34) &amp; &#8220;snapmirror status&#8221; &amp; CHR(34) &amp; &#8221; &gt; &#8221; &amp; outFile &amp; &#8221; 2&gt;&gt;&amp;1 &#8220;, , True)<\/p>\n<p>&#8216; Set a File System Object, so we can read the created file<br \/>\nSet objFSO = CreateObject(&#8220;Scripting.FileSystemObject&#8221;)<\/p>\n<p>&#8216;Check for the file, and read it if it is present<br \/>\nIf objFSO.FileExists(outFile) Then<\/p>\n<p>&#8216;Start Reading the File and Loop through it<br \/>\nSet objFile = objFSO.OpenTextFile(outFile, 1)<br \/>\nDo While Not objFile.AtEndOfStream<\/p>\n<p>sText = objFile.ReadLine<br \/>\nsMessage = sMessage &amp; sText &amp; VbCrLf<\/p>\n<p>Loop<\/p>\n<p>&#8216;Rename the file with the current date time<br \/>\nobjFSO.MoveFile outFile, &#8220;c:pathreplication-&#8221; &amp; Now() &amp; &#8220;.log&#8221;<br \/>\nobjFile.Close<\/p>\n<p>&#8216;Log a success and the message content to the Event log<br \/>\nobjShell.LogEvent EVENTLOG_INFORMATION, sMessage<\/p>\n<p>sSubject = &#8220;NetApp Replication Status as of &#8221; &amp; Now()<\/p>\n<p>&#8216;If the file isn&#8217;t present, there was a problem<br \/>\nElse<\/p>\n<p>sSubject = &#8220;NetApp Replication Status Script Error&#8221;<br \/>\nsMessage = &#8220;NetApp Replication  Status Script Encountered an error with the file &#8221; &amp; outFile<\/p>\n<p>&#8216;Log a failure and the message content to the Event log<br \/>\nobjShell.LogEvent EVENTLOG_ERROR, sMessage<\/p>\n<p>End If<\/p>\n<p>&#8216;Send an e-mail with the Replication status<br \/>\nSendEMail sSubject,sMessage<\/p>\n<p>Sub SendEmail(sSubject,sMessage)<\/p>\n<p>Set objMessage = CreateObject(&#8220;CDO.Message&#8221;)<br \/>\nobjMessage.From = &#8220;SMVI@domain.com&#8221;<br \/>\nobjMessage.To = &#8220;user@domain.com&#8221;<br \/>\nobjMessage.Subject = sSubject<br \/>\nobjMessage.Textbody = sMessage<\/p>\n<p>&#8216;This section provides the configuration information for the remote SMTP server.<br \/>\n&#8216;Normally you will only change the server name or IP.<br \/>\nobjMessage.Configuration.Fields.Item _<br \/>\n(&#8220;http:\/\/schemas.microsoft.com\/cdo\/configuration\/sendusing&#8221;) = 2<\/p>\n<p>&#8216;Name or IP of Remote SMTP Server<br \/>\nobjMessage.Configuration.Fields.Item _<br \/>\n(&#8220;http:\/\/schemas.microsoft.com\/cdo\/configuration\/smtpserver&#8221;) = SMTPServer<\/p>\n<p>&#8216;Server port (typically 25)<br \/>\nobjMessage.Configuration.Fields.Item _<br \/>\n(&#8220;http:\/\/schemas.microsoft.com\/cdo\/configuration\/smtpserverport&#8221;) = 25<\/p>\n<p>objMessage.Configuration.Fields.Update<\/p>\n<p>&#8216;End remote SMTP server configuration section<\/p>\n<p>objMessage.Send<\/p>\n<p>End Sub<\/p><\/blockquote>\n<p><strong>Not too bad for a rough draft<\/strong><br \/>\nThe script executes plink, and outputs the data to a file.  The script then checks to make sure the file was created properly and collects the contents to be e-mailed.  It also renames the file according to the time of execution, so a &#8220;physical&#8221; history of the results can be referred to later.  This script can then be run as a Windows scheduled task to execute at desired intervals.<\/p>\n<p>I have modified the script a little more extensively, including things like posting the results to a database as well as some replication lag alerting.  Look for more information about how to do this in some followup posts.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>When I designed a DR solution a while back, I knew what I needed to do, what the software\/hardware involved would do, but wasn&#8217;t sure &hellip; <\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[12],"tags":[56,72,81,111],"class_list":["post-500","post","type-post","status-publish","format-standard","hentry","category-virtualization","tag-netapp","tag-replication","tag-smvi","tag-vsphere"],"_links":{"self":[{"href":"https:\/\/www.jasemccarty.com\/blog\/wp-json\/wp\/v2\/posts\/500","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.jasemccarty.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.jasemccarty.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.jasemccarty.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.jasemccarty.com\/blog\/wp-json\/wp\/v2\/comments?post=500"}],"version-history":[{"count":0,"href":"https:\/\/www.jasemccarty.com\/blog\/wp-json\/wp\/v2\/posts\/500\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.jasemccarty.com\/blog\/wp-json\/wp\/v2\/media?parent=500"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.jasemccarty.com\/blog\/wp-json\/wp\/v2\/categories?post=500"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.jasemccarty.com\/blog\/wp-json\/wp\/v2\/tags?post=500"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}