Populate your own custom properties on SC VMM 2012

I have been helping a customer to populate their VMM 2012 console with information that they think is good to have, I have made a blog post about this some time ago but now I have added some new valuable information.

The information I retrive are where the VM resides on what CSV volume, if the VM has dynamic VHD´s, if the VM has snapshots and if the snapshots also have been merged, this can only happen when the VM is in Saved State or Stopped on a Win 2008 R2 Hyper-V (this is not an issue on a win 2012 hyper-v as it can live merge)

First I add the Custom Properties

New-SCCustomProperty -Name "DynamicVHD" -AddMember "VM"
New-SCCustomProperty -Name "Snapshots" -AddMember "VM"
New-SCCustomProperty -Name "Datastore" -AddMember "VM"

Here is a screenshot how it looks when you add the custom properties to the console,

Screen Shot 2012-12-17 at 19.41.55

In the powershell script I iterate down through all the snapshots/differencing disks to the parent VHD and check if that is fixed or dynamic. And as you see in the image I check if there is a snapshot or a removed but not merged snapshot (I still have a small problem with the VMM name Checkpoint 😉 )

# Update custom items Snapshots and Dynamic disks, Datastore
# Niklas Akerlund / Lumagate 2012-12-17
if (-not (Get-Module virtualmachinemanager)) {
    Import-Module virtualmachinemanager
Get-SCVMMServer -ComputerName localhost | Out-Null

$VMs = Get-VM 

foreach ($VM in $VMs){
    $Datastore = " "
    $LocationProp = Get-SCCustomProperty -Name "Datastore"
    $SnapShots = Get-SCCustomProperty -Name "Snapshots"    
    $VHDs = $VM | Get-VirtualHardDisk
    $DynDisk = Get-SCCustomProperty -Name "DynamicVHD" 
    $Dyn = $false
    $Merge = $false
    foreach ($VHD in $VHDs){
        if ($VHD.VHDType -eq "DynamicallyExpanding"){
            $Dyn = $true
        if (($VHD.Location -like "*.avhd") -and (($VM | Get-SCVMCheckpoint) -eq $null)){
                $Merge = $true
        $VHDp = $VHD
        while ($VHDp.ParentDisk -ne $Null){
            $VHDp = $VHDp.ParentDisk
            if($VHDp.VHDType -eq "DynamicallyExpanding"){
                $Dyn = $true
    # Update custom values
    $Datastore = $VM.Location.Split("\")[2]
    Set-SCCustomPropertyValue -InputObject $VM -CustomProperty $LocationProp -Value $Datastore
    if ($Dyn){
        Set-SCCustomPropertyValue -InputObject $VM -CustomProperty $DynDisk -Value "Yes" 
        Set-SCCustomPropertyValue -InputObject $VM -CustomProperty $DynDisk -Value "No" 
    if ($VM | Get-SCVMCheckpoint){
        Set-SCCustomPropertyValue -InputObject $VM -CustomProperty $SnapShots -Value "Yes"
        Set-SCCustomPropertyValue -InputObject $VM -CustomProperty $SnapShots -Value "Not Merged"
        Set-SCCustomPropertyValue -InputObject $VM -CustomProperty $SnapShots -Value "No"

As I described in the earlier post you can schedule this to run with scheduled tasks and maybe set it to run every hour or what ever you might prefer.

SCVMM vCheck updated plugin for CSV status reporting

After visiting a customer this friday we talked about their environment and the need to check that their cluster shared volumes in a Windows 2008 R2 SP1 Hyper-V cluster was healthy.

They have started to take host level backup but have not yet got the hardware VSS driver in place and when we checked the backup agent had got into a faulty state and locked the CSV volume in redirected access mode. When we restarted the backup agent  the status got back to online.

Aidian Finn has done a white paper about backup and CSV volumes which describes the redirection and what that can make for impact on the performance. But in short, the cluster node that is the owner will during the redirected access have sole write access to the CSV volume and that means that the other nodes in the cluster must send all storage trafic to that node.

Alan Renouf´s vCheck script is a really easy and good way to keep in a daily control  of your environment, it works for both a VMware vSphere environment and also for Hyper-V with SCVMM thanks to Jan Egil Ring. The best way is to configure it with scheduled tasks and to send a mail every morning.

What I have done is editing the Cluster Shared Volume check plugin to report the status also, as this can be quite important. It is just a minor addition to the plugin, I have also chosen to change so if you set it to 100 the CSV part will always be included in the report and not depending on a percentage space remaining.

Here is the code for the CSV Plugin:

# Start of Settings
# Free space threshold for Hyper-V Cluster Shared Volumes (value in percent)
$CSVFreeSpaceThreshold ="50"
# End of Settings

$Title = "Hyper-V Cluster Shared Volumes"
$Header ="Hyper-V Cluster Shared Volumes"
if($CSVFreeSpaceThreshold -eq 100){
     $Comments = "Hyper-V Cluster Shared Volumes information and state"
    $Comments = "Hyper-V Cluster Shared Volumes with less than $CSVFreeSpaceThreshold percent free, information and state"
$Display = "Table"
$Author = "Jan Egil Ring/Niklas Akerlund"
$PluginVersion = 1.1
$PluginCategory = "Hyper-V"

$FailoverClusters = $VMHostClusters | Where-Object {$_.VirtualizationPlatform -eq "HyperV"}

if ($FailoverClusters)  {

if (!(Get-Module FailoverClusters)) {
	Import-Module FailoverClusters

foreach ($cluster in $FailoverClusters) {
    if($CSVFreeSpaceThreshold -eq 100){
      Get-ClusterSharedVolume -Cluster $cluster.name | Select-Object -Property Name,State -ExpandProperty SharedVolumeInfo | Select-Object @{Name="Cluster";e={$cluster.name}},Name,FriendlyVolumeName,@{ Label= "State"; Expression ={if($_.RedirectedAccess){"Redirected Access"}elseif($_.MaintenanceMode){"Maintenance Mode"}else{"Online"}}},@{ Label = "Size(GB)" ; Expression = { "{0:N2}" -f ($_.Partition.Size/1024/1024/1024) } },@{ Label = "PercentFree" ; Expression = { "{0:N2}" -f ($_.Partition.PercentFree) } },@{ Label = "FreeSpace(GB)" ; Expression = { "{0:N2}" -f ($_.Partition.FreeSpace/1024/1024/1024) } },@{ Label = "UsedSpace(GB)" ; Expression = { "{0:N2}" -f ($_.Partition.UsedSpace/1024/1024/1024) } }
        Get-ClusterSharedVolume -Cluster $cluster.name | Select-Object -Property Name,State -ExpandProperty SharedVolumeInfo | Where-Object {$_.Partition.PercentFree -lt $CSVFreeSpaceThreshold} | Select-Object @{Name="Cluster";e={$cluster.name}},Name,FriendlyVolumeName,@{ Label= "State"; Expression ={if($_.RedirectedAccess){"Redirected Access"}elseif($_.MaintenanceMode){"Maintenance Mode"}else{"Online"}}},@{ Label = "Size(GB)" ; Expression = { "{0:N2}" -f ($_.Partition.Size/1024/1024/1024) } },@{ Label = "PercentFree" ; Expression = { "{0:N2}" -f ($_.Partition.PercentFree) } },@{ Label = "FreeSpace(GB)" ; Expression = { "{0:N2}" -f ($_.Partition.FreeSpace/1024/1024/1024) } },@{ Label = "UsedSpace(GB)" ; Expression = { "{0:N2}" -f ($_.Partition.UsedSpace/1024/1024/1024) } }