Hyper-V Resource Metering

Hyper-V Resource Metering

In this video we explore the new resource metering features in Hyper-V 2012 and 2012R2. We talk about the structure and uses of resource metering and then we use PowerShell to implement resource metering on a clustered configuration.

Resource Metering Overview

Resource metering enables administrators to collect data about the resource usage of a VM or pool of VMs. This data is presented as average utilization over a time period. The time period is the time sense the metering was enabled, or sense the last metering reset. This data can be used for creating chargeback or show back models. As you will soon see, the data from resource metering is relatively simple. It is not meant to replace an enterprise performance monitoring tool such as System Center Operations Manager (SCOM). Resource metering is something that can only be configured via the PowerShell interface.

Resource metering allows you to collect information about the VM’s CPU, memory, network and storage utilization. The data collected is stored in the virtual machine’s configuration file. This means that the resource metering data will stay with the VM when it is migrated to another host or cluster node.

A hierarchy of resource pools can be created to group VMs. The groups can represent any logical collection that is meaningful in your environment. A VM’s resource may only belong to one resource group at a time. The resource group gets its totals from the data stored in the VM’s configuration files. As such, if a host has no VMs on it, its resource groups will not report any values and will be disabled. When creating a resource pool a ‘pool type’ must be defined. While it is possible to configure different names for each of the resource pool types, it may be easier to name all of the pools for a particular logical collection with the same name as we have done in the video. This makes collecting the data much easier, but is not a requirement.

PowerShell Command to Manage Resource Metering

Enable/Disable Resource Metering
Enable-VMResourceMetering
Disable-VMResourceMetering
Configure VM Resources for Metering
Set-VMProcessor
Set-VMHardDiskDrive
Set-VMMemory
Set-VMNetworkAdapter
Add-VMNetworkAdapterAcl
Remove-VMNetworkAdapterAcl
Creating/Removing Resource Pools
New-VMResourcePool
Set-VMResourcePool
Remove-VMResourcePool
Measuring VMs and Pools
Measure-VM
Measure-VMResourcePool
Reset-VMResourceMetering

Resource Metering Demo!

In the video we did a demo where we created resource pools called Pool1 on cluster HVC0 for our 3 VMs (App-1,2,3). We then gathered pool metering information from all of the nodes and displayed the aggregated data.
Here is the script that we used in the video:
ClusterResourcePoolFunctions.PS1

PowerShell Code for Resource Metering

###Demo 1 functions - Demo 1 Enable VM and Measure
###Show Cluster Resource Pool
function Get-ClusterResourcePool {
    param ($Cluster = ".",$ResourcePool = "*")
    $Nodes = (Get-ClusterNode -Cluster $Cluster).name
    Get-VMResourcePool -ComputerName $nodes -Name $ResourcePool
}
### Enable Cluster Resource Metering VM
function Enable-ClusterResourcePoolVM {
    param ($Cluster = ".", $VMFilter = "*")
    $Nodes = (Get-ClusterNode -Cluster $Cluster).name
    $VMS = Get-VM -ComputerName $Nodes -VMName $VMFilter -ErrorAction SilentlyContinue
    if($VMs){ #VMs found!
        $VMs |Enable-VMResourceMetering
    } else {
        "No Vms Match Filter"
    }
}
### Measure Cluster Resource Pool VMs
function Measure-ClusterResourcePoolVM{
    param ($Cluster = ".", $VMFilter = "*")
    $Nodes = (Get-ClusterNode -Cluster $Cluster).name
    Measure-VM -ComputerName $nodes -Name $VMFilter -ErrorAction SilentlyContinue
}

#Demo 1 Enable VM and Measure
Get-ClusterResourcePool -Cluster HVC0
Enable-ClusterResourcePoolVM -Cluster HVC0 -VMFilter App*
start-vm -ComputerName HVC0N1 -Name App-2
Get-ClusterResourcePool -Cluster HVC0
Measure-ClusterResourcePoolVM -Cluster HVC0 -VMFilter App-*
stop-vm -ComputerName HVC0N1 -Name App-2

###Demo 2 functions

###Create Cluster Resource Pool
Function New-ClusterResourcePool {
    param ($Cluster = ".", $ResourcePool = "Pool1", $StoragePath = "NoneSupplied", $SwitchName="HVSwitch")
    $Nodes = (Get-ClusterNode -Cluster $Cluster).name
    New-VMResourcePool -ComputerName $Nodes -Name $ResourcePool -ResourcePoolType Ethernet,Processor,Memory
    If ($StoragePath -eq "NoneSupplied"){$StoragePath = (Get-ClusterSharedVolume -Cluster $cluster| select -ExpandProperty sharedVolumeInfo).friendlyvolumename}
    New-VMResourcePool -ComputerName $Nodes -Name $ResourcePool -ResourcePoolType VHD -Paths $StoragePath
    Get-VMSwitch -ComputerName $Nodes -Name $SwitchName| Add-VMSwitch -ResourcePoolName $ResourcePool
}
### Set Cluster Resource Pool VM Assignment
Function Set-ClusterResourcePoolVM {
    param ($Cluster = ".",$ResourcePool="Primordial", $VMFilter = "*")
    $Nodes = (Get-ClusterNode -Cluster $Cluster).name
    $VMS = Get-VM -ComputerName $Nodes -VMName $VMFilter -ErrorAction SilentlyContinue
    if($VMs){ #VMs found!
        foreach ($VM in $VMS) {
            Write-Debug "Setting resource pool $ResourcePool on VM $($VM.name)"
            $VM|Set-VMProcessor -ResourcePoolName $ResourcePool
            $VM|Set-VMMemory -ResourcePoolName $ResourcePool
            $VM|Get-VMNetworkAdapter| Set-VMNetworkAdapter -ResourcePoolName $ResourcePool
            $VM|Get-VMNetworkAdapter| Connect-VMNetworkAdapter -UseAutomaticConnection #ENABLES LIVE MIGRATION BETWEEN HOSTS IN CLUSTER
            $VM|Get-VMHardDiskDrive| Set-VMHardDiskDrive -ResourcePoolName $ResourcePool
        }
    } else {#no vms found!
        "No VMs match filter"
    }
}
### Get Cluster Resource Pool VM Assignment
Function Get-ClusterResourcePoolVM {
    param ($Cluster = ".", $VMFilter = "*")
    $Nodes = (Get-ClusterNode -Cluster $Cluster).name
    $VMS = Get-VM -ComputerName $Nodes -VMName $VMFilter -ErrorAction SilentlyContinue
    if($VMs){ #VMs found!
        foreach ($VM in $VMS) {
            Write-Debug "Getting resource pool info for VM $($VM.name)"
            $MyObj = ""| select VM, CPU, RAM, Disk, Network
            $MyObj.VM = $VM.name
            $Myobj.CPU = $vm| Get-VMProcessor|select -ExpandProperty ResourcePoolName
            $MyObj.RAM = $vm| Get-VMMemory|select -ExpandProperty ResourcePoolName
            $MyObj.Network = ($vm| Get-VMNetworkAdapter|select -ExpandProperty PoolName|select -Unique) -join ","
            $MyObj.Disk = ($vm| Get-VMHardDiskDrive|select -ExpandProperty PoolName|select -Unique) -join ","
            $MyObj
        }
    } else {#no vms found!
        "No VMs match filter"
    }
}
### Measure Cluster Resource Pool
function Measure-ClusterResourcePool {
    param ($Cluster = ".",$ResourcePool)
    $Nodes = (Get-ClusterNode -Cluster $Cluster).name
    $Pools = Get-VMResourcePool -ComputerName $Nodes | where-Object { $_.ResourceMeteringEnabled -eq "True"}|%{$_.name}| Select-Object -Unique
    foreach ($Pool in $Pools){
        $MyObj = ""| select PoolName,  AvgCPU, AvgRAM, TotalDisk, NetworkInbound, NetworkOutbound
        $MyObj.PoolName = $Pool
        $MyObj.AvgCPU = (Measure-VMResourcePool -ComputerName $nodes -name $pool -ResourcePoolType Processor `
                             -ErrorAction SilentlyContinue|Measure-Object -sum -Property AvgCPU).sum
        $MyObj.AvgRAM = (Measure-VMResourcePool -ComputerName $nodes -name $pool -ResourcePoolType Memory -ErrorAction SilentlyContinue|Measure-Object -sum -Property AvgRAM).sum
        $MyObj.TotalDisk = (Measure-VMResourcePool -ComputerName $nodes -name $pool -ResourcePoolType VHD -ErrorAction SilentlyContinue|Measure-Object -sum -Property TotalDisk).sum
        #Networking
        $networkGroup = Measure-VMResourcePool -computername $nodes -name $pool -ResourcePoolType Ethernet -ErrorAction SilentlyContinue | select -ExpandProperty NetworkMeteredTrafficReport|Group-Object -Property direction
        $MyObj.NetworkInbound  =  ($networkGroup|?{$_.name -eq "Inbound"}|select -ExpandProperty group|Measure-Object -Property TotalTraffic -Sum).sum
        $MyObj.NetworkOutbound  =  ($networkGroup|?{$_.name -eq "Outbound"}|select -ExpandProperty group|Measure-Object -Property TotalTraffic -Sum).sum
        $MyObj
    }
}

#Demo 2 Create, assign and measure pool
New-ClusterResourcePool -Cluster HVC0 -ResourcePool Pool1
Get-ClusterResourcePool -Cluster HVC0
Get-ClusterResourcePoolVM -Cluster HVC0 -VMFilter App* | Format-Table -AutoSize
Set-ClusterResourcePoolVM -Cluster HVC0 -ResourcePool pool1 -VMFilter App*
Get-ClusterResourcePoolVM -Cluster HVC0 -VMFilter App* | Format-Table -AutoSize
Start-VM -ComputerName (Get-ClusterNode -Cluster HVC0).name -Name App*
Measure-ClusterResourcePool -Cluster HVC0 -ResourcePool pool1

###Demo 3 functions
### Reset Cluster Resource Metering VM
function Reset-ClusterResourcePoolVM {
    param ($Cluster = ".", $VMFilter = "*")
    $Nodes = (Get-ClusterNode -Cluster $Cluster).name
    $VMS = Get-VM -ComputerName $Nodes -VMName $VMFilter -ErrorAction SilentlyContinue
    if($VMs){ #VMs found!
        $VMs |Reset-VMResourceMetering
    } else {
        "No Vms Match Filter"
    }
}
### Reset Cluster Resource Metering
function Reset-ClusterResourcePool {
    param ($Cluster = ".",$ResourcePool="*")
    $Nodes = (Get-ClusterNode -Cluster $Cluster).name
    Reset-VMResourceMetering -ComputerName $nodes -ResourcePoolName $ResourcePool -ErrorAction SilentlyContinue
}

#Demo 3 Reseting resource metering
Stop-VM -ComputerName (Get-ClusterNode -Cluster HVC0).name -Name App*
measure-ClusterResourcePoolVM -Cluster HVC0 -VMFilter App*
Reset-ClusterResourcePoolVM -Cluster HVC0 -VMFilter App-2
measure-ClusterResourcePoolVM -Cluster HVC0 -VMFilter App*
Reset-ClusterResourcePool -Cluster HVC0 -ResourcePool pool1
measure-ClusterResourcePool -Cluster HVC0 -ResourcePool pool1

#Demo 4 functions
### Disable Cluster Resource Metering VM
function Disable-ClusterResourcePoolVM {
    param ($Cluster = ".", $VMFilter = "*")
    $Nodes = (Get-ClusterNode -Cluster $Cluster).name
    $VMS = Get-VM -ComputerName $Nodes -VMName $VMFilter -ErrorAction SilentlyContinue
    if($VMs){ #VMs found!
        $VMs |Disable-VMResourceMetering
    } else {
        "No Vms Match Filter"
    }
}
###Remove Cluster Resource Pool
function Remove-ClusterResourcePool {
    param ($Cluster = ".",$ResourcePool)
    $Nodes = (Get-ClusterNode -Cluster $Cluster).name
    Remove-VMResourcePool -ComputerName $Nodes -Name $ResourcePool -ResourcePoolType Ethernet,Processor,Memory,VHD
}

#Demo 4 Remove resource pools
Set-ClusterResourcePoolVM -Cluster HVC0 -ResourcePool "Primordial" -VMFilter App*
Disable-ClusterResourcePoolVM -Cluster HVC0 -VMFilter App*
Remove-ClusterResourcePool -Cluster HVC0 -ResourcePool pool1
Get-ClusterResourcePool -Cluster HVC0
Get-ClusterResourcePoolVM -Cluster HVC0 -VMFilter App*| Format-Table * -AutoSize

Resources

TechNet: Introduction to Resource Metering
MSDN: Hyper-V Resource Metering Overview

2 thoughts on “Hyper-V Resource Metering

Leave a Reply

Your email address will not be published. Required fields are marked *