Forum Discussion

Kelemvor's avatar
Kelemvor
Icon for Expert rankExpert
5 months ago

Anyone know of a way to monitor for SNapshot age on a Hyper-V machine?

We have some checks that monitor our VMWare system for Snapshots.  Once they are over 72 hour old, we get an alert. I haven’t been able to find a way to do the same thing for our Hyper-V servers.  Does anyone happen to know if that’s possible?  I didn’t see anything in the Exchange but just through I’d ‘check in case someone knew of anything.

I can pull the data with Powershell via the get-vm|get-vmsnapshot command.  Not sure if that’s usable in LM somehow.

Thanks.

8 Replies

  • The problem with your discovery script is that you're setting the wildvalue to the name of the VM, which means you're intending only to track the VM itself, not the age of the snapshots for the VM. You're right that you'll need a line of output per VM per snapshot. However, it should look more like this:

    $hostname = '##SYSTEM.HOSTNAME##'
    
    Invoke-Command -ComputerName $hostname -ScriptBlock { 
        $vms = Get-VM
        foreach ($vm in $vms){
            $VMName = $vm.Name
            $VMState = $vm.State
            $snapshots = Get-VMSnapshot -VMName $vm.Name
            foreach ($snapshot in $snapshots) {
                $SnapshotName = $snapshot.Name
                $SnapshotID = $snapshot.Id
                Write-Host "$SnapshotID##$SnapshotName######vm.name=$VMName&vm.state=$VMState"
            }
        }
    }
    # return with a response code that indicates we ran successfully
    Exit 0;

    This will make one instance per snapshot. You can filter the snapshots using a discovery filter based on the auto.vm.state instance level property created by the script and you can group based on the auto.vm.name instance level property created by the script.

    Once that's done, the only thing you need to know during collection about each snapshot is its ID (the same one defined in discovery) and the age:

    $hostname = '##SYSTEM.HOSTNAME##'
    
    Invoke-Command -ComputerName $hostname -ScriptBlock { 
        $vms = Get-VM
        $currentDate = Get-Date
        foreach ($vm in $vms){
            $snapshots = Get-VMSnapshot -VMName $vm.Name
            foreach ($snapshot in $snapshots) {
                $SnapshotAge = ($currentDate - $snapshot.CreationTime).Days
                $SnapshotID = $snapshot.Id
                Write-Host "$SnapshotID.AgeInDays: $SnapshotAge"
            }
        }
    }
    Exit 0

    The only thing remaining would be to create your datapoint. It would use "key-value pairs" and the key would be "##WILDVALUE##.AgeInDays"

    • Marcel's avatar
      Marcel
      Icon for Neophyte rankNeophyte

      Thanks, this is working now!

      One more question. With the monitoring script, can you query just the concerning snapshot using a filter, instead of looping through all the snapshots? Just curious because of the possible performance impact of querying all the snapshots. So the script would be something like this:

      $hostname = '##SYSTEM.HOSTNAME##';
      $wildvalue = '##WILDVALUE##'
      $VM = '##auto.VM.Name##'
      
      Invoke-Command -ComputerName $hostname -ScriptBlock { 
      
      $snapshot = Get-VMSnapshot -vmname $Using:VM | ? {$_.ID -eq $Using:wildvalue} 
      
      #rest of code...
      
      }

       

      • Stuart_Weenig's avatar
        Stuart_Weenig
        Icon for Mastermind rankMastermind

        You can definitely do that; it would be a SCRIPT datasource (one collection task per instance) instead of a BATCHSCRIPT datasource (one collection task for all instances). Efficiency/performance reasons is the main factor in deciding between SCRIPT and BATCHSCRIPT. 

  • I'm working on the same and already have some scripts in place.

    Auto discovery script:

    $hostname = '##SYSTEM.HOSTNAME##';
    
    Invoke-Command -ComputerName $hostname -ScriptBlock { 
    $vms = Get-VM | Where-Object {$_.State -eq 'Running'}
    
    foreach ($vm in $vms) 
    {
        $snapshots = Get-VMSnapshot -VMName $vm.Name
            foreach ($snapshot in $snapshots) {
                        $VMName       = $vm.Name
                        $SnapshotName = $snapshot.Name
                     # write out the instance data
                    Write-Host "$VMName##$SnapShotName";
            }
    }
    }
    
    # return with a response code that indicates we ran successfully
    Exit 0;

    Monitoring script:

    $hostname = '##SYSTEM.HOSTNAME##';
    
    Invoke-Command -ComputerName $hostname -ScriptBlock { 
    
    $vms = Get-VM | Where-Object {$_.State -eq 'Running'}
    $currentDate = Get-Date
    
    foreach ($vm in $vms) 
    {
        $snapshots = Get-VMSnapshot -VMName $vm.Name
            foreach ($snapshot in $snapshots) {
                $snapshotAge = ($currentDate - $snapshot.CreationTime).Days
                        $VMName       = $vm.Name
                        $SnapshotName = $snapshot.Name
                        $CreationTime = $snapshot.CreationTime
                        $AgeInDays    = $snapshotAge            
        # write out the instance data                
        Write-Host "SnapshotName=${SnapshotName}";
        Write-Host "VMName=${VMName}";
        Write-Host "CreationTime=${CreationTime}";
        Write-Host "AgeInDays=${AgeInDays}";            
     }
    }
    }
    
    # return with a response code that indicates we ran successfully
    Exit 0;

    However this doesn't seem to work. What am I missing?

    I also struggle to get the snapshots grouped per VM. The group method is regular expression with Parameters = useValue="value" dynamicGroup="\w+". Why doesn't this work?

  • You’ll likely end up with two scripts, a discovery script and a collection script.

    Discovery:

    This script is meant to enumerate the instances to LogicMonitor. The goal is to output a list of the objects you’ll be monitoring. Depending on how you want to do it, this will either be the list of VMs or the list of snapshots. This PS script would execute on the collector, but use the invoke-command with the -computer argument to actually execute the command remotely on the target HPV. The output will be multiple lines, where each line represents a VM or snapshot. 

    You could list the snapshots using the get-vmlget-vmsnapshot command. The required output is described here. I recommend ticking the box that says “Use Wildvalue as Unique Identifier” (I’ll explain if you’re interested why). Tick the “Multi-instance” and “Enable Active Discovery” tickboxes. Then you can select “Embedded PowerShell Script” and paste in your script. I recommend testing your script on the collector debug console since the test options on the DS editor aren’t conducive to actual debugging.

    I recommend setting a property on the instance containing the name of the VM the snapshot belongs to. This will allow you to auto-group the instances by VM.

    Collection:

    This script will be very similar to the discovery script; it will use the invoke-command with the -computer argument to run on the collector but execute on the target HPV remotely. The output syntax is described here.

    Your datapoints would use the “multi-line key value pairs” processor and the key would look like this: ##WILDVALUE##.<datapointname> where <datapointname> is the part that comes after the dot and before the equals sign in your script output.

    I’m not a powershell guy, so someone else might have to get you started with template scripts. 

  • I’ve never created anything like this before.  Do I just run the script and LM will parse it and figure things out?

    We have all our HPV Hosts in a group so I could point something at the group, or apply it based on the name.  If I run get-vm|get-vmsnapshot on the host, it gives me all the info I need in a table.  Would need to check the date column and convert that to Age In Hours.   Would need to put all the data into the Raw Data and then set an alert for Age In Hours > 72 I guess.

    Does  anyone have an example of something similar i could look at to see how this should work?

    Thanks.

  • Yep, that’s it. Invoke-Command -computer <hyper-v name/ip>. Remember the powershell runs on the collector, which is why you need to run it remotely, unless the get-vm|get-vmsnapshot cmdlet has a remote option built in. 

    I suggest a discovery script that would list out either the VMs or the snapshots (probably the VMs) and a batchscript collection script that lists out the age of the oldest snapshot on the VM (or the age of each snapshot if your discovery lists each snapshot individually).

  • I didn’t see anything in Exchange either but you should be able to run that powershell command in a datasource, perhaps via Invoke-Command to the Hyper-V server. Then calculate the age from CreationTime of the checkpoint and provided that as a datapoint to LM.