Using PowerShell to take Virtual Server snapshots… (Part Three)

Analysis
Nov 4, 20073 mins

This is my third posting in this series.  In the first posting, I described the different components that would be needed for this script.  Then in the second posting, I started explaining how the first part of the script worked.  Now, in this third posting, we will dive into a meatier portion of the script and figure out the code for taking the VM snap shots.  Let’s get started!

To kick things off, we first loop through the VMs and pause each one:

foreach ($Server in $Servers){   # To store the path information we extend the VM’s    # Next we use some logic to see if the VM is running.      # Now for some progress fun!

   # First we need to create an object for the VM itself.

   $VM = $MSVS.findVirtualMachine($Server.Name)

   # Like the VS object we need to also set the security on the VM object.

   $Null = [Microsoft.VirtualServer.Interop.Powershell]::SetSecurity($VM) 

   # We also need to grab some information where the VMs files are.

   # Note that this script will only work if all the files are located

   # where the VMC file is.

   $Drive = split-path $VM.File -qualifier

   $Path = split-path $VM.File

   # object with location info (kinda of like a squirrel hiding its nuts!)

   add-member -inputObject $Server -membertype noteProperty `

      -name “Drive” -value $Drive

   add-member -inputObject $Server -membertype noteProperty `

       -name “Path” -value $Path

   if ($VM.State -eq 5){

      # If the VM is running we need to pause it.

      $Progress = $VM.Save()

      $Null = `

      [Microsoft.VirtualServer.Interop.Powershell]::SetSecurity($Progress)

      while ($Progress.PercentCompleted -lt 100){

         write-progress -Activity “Saving – $($Server.Name)” `

         -Status “Progress:” `

         -PercentComplete ($Progress.PercentCompleted)

            }

      # Need to state if the VM was paused by the script.

         add-member -inputObject $Server -membertype noteProperty `

         -name “Paused” -value “Yes”

         write-progress -Status “Done” -completed $True

         }

      else{

         # Need to state if the VM was not paused by the script.

         add-member -inputObject $Server -membertype noteProperty `

         -name “Paused” -value “No”

         }

   }

Ok, that was a bit of code just to pause the VMs.  The next step is to take a snapshot for each VM:

$Drives = $Servers | select Drive -unique   # Here is where we start using vshadow.exe   # Here is something a little different.  I’m using the script    # Then using some RegEx magic we strip that information from the file.   # Next we add that information to the Drive object.

foreach ($Drive in $Drives){

   write-progress -Activity “Taking shapshot – $($Drive.Drive)” `

   -Status “Stand by…”

   $Null = .Resourcesvshadow.exe -script=var -p $Drive.Drive

   # switch parameter to write shadow copy set ID to a VAR file.

   $ID = get-content var

   $ID = [RegEx]::Matches($ID, ‘(?

   add-member -inputObject $Drive -membertype noteProperty `

      -name “ID” -value $ID[0].toString()

   # We also delete that var file

   remove-item var

   }

Ok, that’s it for this posting.  In my next posting we will finish up the script.  Please remember to mind the formatting.  Also, items in this script are not optimized.  I’m doing this for a reason, one it’s easier to read.  Two, I stripped out all of the messaging, error handling, and logging.  My production scripts tend to be a little overkill on handling things.  But, then again… if this becomes a backup solution then it needs to work flawlessly.  With that in mind, if this code is used, you may want to add that stuff back in.