Option Explicit '----------------------------------------------------------------- ' Procedure: Snapshot.vbs ' Author: Scott Vintinner ' Last Edit: 07/19/2017 ' Purpose: This script will manage NetApp snapshots for the ' specified drive(s) using SnapDrive. '----------------------------------------------------------------- '-------- 'Settings '-------- 'Location of snapdrive executable Const SDCLI = "C:\Program Files\NetApp\SnapDrive\sdcli.exe" 'Indicate how many snapshots you want to keep. Const snapshotCount = 4 'Indicate the naming convention for the snapshot (a date-time will be added to the end). Const snapshotPrefix = "dmindex-sdcli-snapshot" 'SMTP Mail Server Const smtpServer = "5.5.5.5" 'Send emails to this address Const toAddress = "myaddress@mycompany.com" 'Emails come from this address Const fromAddress = "servername@mycompany.com" Dim drives ' Identify the drives that we want to snapshot ' NOTE: the drive parameter can be either a drive letter (ex: "G") or a mount point folder (ex: "C:\mydirectory"). ' Examples: ' drives = Array("E","F","G") drives = Array("E") '-------- 'Main '-------- 'Declare our scripting objects Dim fs, scriptShell, i Set fs = CreateObject ("Scripting.FileSystemObject") Set scriptShell = CreateObject("WScript.Shell") 'Figure out the current computer name Dim network, serverName Set network = WScript.CreateObject("WScript.Network") serverName = network.ComputerName 'Open the LogFile for writing Dim logFile, errorCount, logFileName errorCount=0 On Error Resume Next logFileName=WScript.ScriptFullName & " - " & serverName & "-SNAPSHOT.log" Set logFile = fs.CreateTextFile(logFileName) LogEntry("Logfile opened") If Err.Number<>0 Then wscript.echo("Unable to open the file(s) for writing: " & logFileName) wscript.quit End If On Error Goto 0 'Loop through the list of drives and snapshot them For i=0 to Ubound(drives) LogEntry("") LogEntry("") LogEntry("--------------------STARTING------------------------") Call ManageSnapshots(drives(i), snapshotCount, snapshotPrefix) Call TakeSnapshot(drives(i), snapshotPrefix) Next logFile.Close Set logFile=Nothing If errorCount > 0 then Call SendEmail(toAddress, _ fromAddress, _ "Error while taking a snapshot on " & serverName, smtpServer, _ "There was an error while taking a snapshot on " & serverName & ". Please review the attached log file for more info.", _ array(logFileName)) End If 'Clean Up Set fs=Nothing Set scriptShell=Nothing '------------- 'TakeSnapshot '------------- Sub TakeSnapshot(driveLetter, snapshotName) Dim execResult, execCommand, snapSuccess, line LogEntry("Creating new snapshot...") snapSuccess = false snapshotName = snapshotName & "_recent" 'Take the new snapshot execCommand = SDCLI & " snap create -s " & snapshotName & " -D " & driveLetter LogEntry("Launching command: " & execCommand) Set execResult = scriptShell.Exec(execCommand) Do While Not execResult.StdOut.AtEndOfStream line=execResult.StdOut.ReadLine() LogEntry(line) If Instr(line, "The operation completed successfully.") > 0 Then snapSuccess=true End If Loop If Not snapSuccess Then LogError("***It seems that the sdcli.exe command has failed!***") Else LogEntry("--------------------FINISHED------------------------") End If End Sub '--------------- 'ManageSnapshots '--------------- Sub ManageSnapshots(driveLetter, snapshotCount, snapshotPrefix) Dim execResult, execCommand, line, snapshots, index, snapshotName, TypeLib snapshots=Array("") 'Generate a list of existing snapshots that match our prefix execCommand = SDCLI & " snap list -d " & driveLetter LogEntry("Launching command: " & execCommand) Set execResult = scriptShell.Exec(execCommand) Do While Not execResult.StdOut.AtEndOfStream line=execResult.StdOut.ReadLine() 'Parse out the name of the snapshot and stuff it into an array index = InStr(1,line," ") line = Trim(Mid(line,1,index)) line = Replace(line, Chr(9), "") 'Replace Tab characters If InStr(1,line,snapshotPrefix) > 0 Then snapshots(UBound(snapshots,1)) = Trim(line) LogEntry("Found snapshot: " & snapshots(Ubound(snapshots,1)) ) 'Add room for the next entry in the array Redim Preserve snapshots(ubound(snapshots,1)+1) End If Loop LogEntry("Found " & ubound(snapshots,1) & " manageable snapshots. Limit is: " & snapshotCount & ".") 'If there are too many snapshots, delete the oldest one If ubound(snapshots,1) >= snapshotCount Then LogEntry("Limit of " & snapshotCount & " reached. Deleting oldest snapshot") 'Delete the oldest snapshot (should be the last one added to the snapshots array) 'per Chris Watkins (@ChrisWatkinsUK): The line below is for newer clustered ontap filers. Where the order 'of snapshots returned by the command is reversed. execCommand = SDCLI & " snap delete -d " & driveLetter & " -s " & snapshots(ubound(snapshots,1)-snapshotCount) 'original 7-mode sort order 'execCommand = SDCLI & " snap delete -d " & driveLetter & " -s " & snapshots(ubound(snapshots,1)-1) LogEntry("Launching command: " & execCommand) Set execResult = scriptShell.Exec(execCommand) Do While Not execResult.StdOut.AtEndOfStream line=execResult.StdOut.ReadLine() LogEntry(line) If Instr(line, "The operation completed successfully.") > 0 Then LogEntry("Snapshot: " & snapshotName & " successfully deleted.") Else If Instr(line, "does not exist and cannot be deleted") > 0 Then LogEntry("Oldest Snapshot: " & snapshotName & " did not exist.") End If End If Loop End If 'If there is an _recent snapshot, rename it For index=0 To UBound(snapshots,1)-1 If InStr(1,snapshots(index),"_recent") > 0 Then LogEntry("Renaming previous _recent snapshot...") Set TypeLib = CreateObject("Scriptlet.TypeLib") snapshotName = snapshotPrefix & "-" & Left(TypeLib.Guid,Len(TypeLib.guid)-2) 'strip off strange nul chars returned by Typelib.GUID Set TypeLib = Nothing execCommand = SDCLI & " snap rename -d " & driveLetter & " -o " & snapshots(index) & " -n " & snapshotName LogEntry("Launching command: " & execCommand) Set execResult = scriptShell.Exec(execCommand) Do While Not execResult.StdOut.AtEndOfStream line=execResult.StdOut.ReadLine() LogEntry(line) If Instr(line, "The operation completed successfully.") > 0 Then LogEntry("Snapshot: " & snapshots(index) & " successfully renamed to " & snapshotName & ".") Else LogError("Snapshot: " & snapshots(index) & " could not be renamed.") End If Loop End If Next End Sub '-------- 'LogEntry '-------- Sub LogEntry(logText) logFile.Write(now & ": " & logText & vbcrlf) wscript.StdOut.WriteLine(now & ": " & logText) End Sub Sub LogError(logText) LogEntry(logText) errorCount=errorCount+1 End Sub '-------- 'SendEmail '-------- Sub SendEmail(recipient, sender, subject, smtpServer, message, attachments) On Error Resume Next Dim cdo Set cdo = CreateObject("CDO.Message") cdo.From = sender cdo.To = recipient cdo.Subject = subject cdo.HTMLBody = message Dim attachment For each attachment in attachments cdo.AddAttachment(attachment) Next cdo.Configuration.Fields.Item("http://schemas.microsoft.com/cdo/configuration/sendusing") = 2 cdo.Configuration.Fields.Item("http://schemas.microsoft.com/cdo/configuration/smtpserver") = smtpServer cdo.Configuration.Fields.Item("http://schemas.microsoft.com/cdo/configuration/smtpserverport") = 25 cdo.Configuration.Fields.Update cdo.send Set cdo = nothing If Err.Number<>0 then Wscript.Echo("Error Sending Email!" & vbcrlf & Err.Description) On Error Goto 0 End Sub