Skip to content

Instantly share code, notes, and snippets.

@flakshack
Created July 19, 2017 15:41
Show Gist options
  • Select an option

  • Save flakshack/cc6e2e52f49fc046c8e5c7c533a9a9d2 to your computer and use it in GitHub Desktop.

Select an option

Save flakshack/cc6e2e52f49fc046c8e5c7c533a9a9d2 to your computer and use it in GitHub Desktop.

Revisions

  1. flakshack created this gist Jul 19, 2017.
    251 changes: 251 additions & 0 deletions snapshot.vbs
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,251 @@
    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 = "[email protected]"
    'Emails come from this address
    Const fromAddress = "[email protected]"

    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