Everything about Web and Network Monitoring

Home > Server Management > Windows Servers Monitoring > Monitoring Hyper-V With PowerShell on Monitis

Monitoring Hyper-V With PowerShell on Monitis

hypervIn previous articles we learned how to perform complex monitoring of Microsoft Windows Servers (How to Monitor Windows Servers with VBScript, WMI and Monitis) and IIS (Monitoring IIS With VBScript via Monitis; It’s so Easy!using ) VBScript. In this article we will describe how to monitor Hyper-V and add Custom Monitors and pages to your Monitis account (see also 30 Ways to Improve Hyper-V Virtualization).

About Hyper-V

Hyper-V is the virtualization solution included in all Windows Server 2008 versions. It is tightly integrated in the operating system (OS) and other Microsoft products such as those of the System Center family.  It delivers performance and features — such as high availability — at the level of the best competitors on the market, for example, Live Migration and, with the latest release in Windows 2008 R2 SP1, also Dynamic Memory. It also exposes a lot of internal functions and metrics to be used in scripts and other utilities, enabling you to automate deployment and other operations as well as allowing a precise monitoring of your virtualization infrastructure.

Monitoring Hyper-V

When it comes to monitoring virtualization, one of the major challenges is to identify which virtual machine is using which host resource. Windows Server provides several counters that help you identify how resources are consumed, some general and some specific to the Hyper-V subsystem.

The parameters to be monitored are:

% Processor Time
Processor is crucial for the smooth operation of virtual machines. And it is crucial to keep load average below 60-70%. If a VM is consistently using a lot of CPU it must be quickly troubleshooted or moved to another host.
In PowerShell you can get host performance metrics with this command:

(get-counter '\Processor(_Total)\% Processor Time').CounterSamples[0].CookedValue
(get-counter '\Processor(_Total)\% Privileged Time').CounterSamples[0].CookedValue

You can also monitor Virtual Processors on guest VMs:

(get-counter '\Hyper-V Hypervisor Virtual Processor(XPHV:Hv VP 0)\% Total Run Time').CounterSamples[0].CookedValue
(get-counter '\Hyper-V Hypervisor Virtual Processor(XPHV:Hv VP 0)\% Guest Run Time').CounterSamples[0].CookedValue

When monitoring guests, you have to tailor the command to your specific environment, replacing the name of the VM and the number of the processor to monitor inside the parenthesis.

Disk transferred bytes
This is the amount of bytes that is read from or written to the disk.  For the host, select the counter instance related to the Physical disk hosting your VHDs, for example:

(get-counter '\PhysicalDisk(0 C:)\Disk Read Bytes/sec').CounterSamples[0].CookedValue
(get-counter '\PhysicalDisk(0 C:)\Disk Write Bytes/sec').CounterSamples[0].CookedValue

For your virtual machines select the counter instance related to the VMs that you want to monitor.

(get-counter '\Hyper-V Virtual IDE Controller(XPHV:Ide controller)\Read Bytes/sec').CounterSamples[0].CookedValue
(get-counter '\Hyper-V Virtual IDE Controller(XPHV:Ide controller)\Write Bytes/sec').CounterSamples[0].CookedValue

Network transferred bytes
This is the amount of bytes that is received from or sent to the network. If the value is consistently above 50% of the adapter bandwidth, consider adding network adapters. Also monitor your network infrastructure to identify bottlenecks outside your Hyper-V host.  For the host, select the counter instance related to the physical network adapters used by your virtual machines, for example:

(get-counter '\Network Interface(D-Link DFE-538TX 10_100 Adapter)\Bytes Received/sec').CounterSamples[0].CookedValue
(get-counter '\Network Interface(D-Link DFE-538TX 10_100 Adapter)\Bytes Sent/sec').CounterSamples[0].CookedValue

For your virtual machines, select the counter instance related to network adapter on the VMs that you want to monitor.

(get-counter '\Hyper-V Virtual Network Adapter(D-Link DFE-538TX 10_100 Adapter - VirtualBox Bridged Networking Driver Miniport__DEVICE_{E34F3122-DB37-4745-86BD-456EB0666F0A})\Bytes Received/sec').CounterSamples[0].CookedValue
(get-counter '\Hyper-V Virtual Network Adapter(D-Link DFE-538TX 10_100 Adapter - VirtualBox Bridged Networking Driver Miniport__DEVICE_{E34F3122-DB37-4745-86BD-456EB0666F0A})\Bytes Sent/sec').CounterSamples[0].CookedValue

Hyper-V host Memory
On the host, you should keep available at least 20% of the installed memory.  Monitor available memory with this command:

(get-counter '\Memory\Available Mbytes').CounterSamples[0].CookedValue

Also monitor hard page faults that occur when memory pages are read or written from the disk. This value should stay below 500-1000 pages per second. The command is:

(get-counter '\Memory\Pages/sec').CounterSamples[0].CookedValue

Guest Virtual Machines memory
With the latest version of Hyper-V included in Windows Server 2008 R2 SP1, it is very easy to monitor VMs configured for using Dynamic Memory. The value of the counter Average Pressure measures memory availability, and below 100, it means that the VM has more memory than it needs, while above 100 means that the VM is not allocated the memory that it needs. A good value for this metric is 80.
The command is:

(get-counter '\Hyper-V Dynamic Memory VM(XPHV)\Average Pressure').CounterSamples[0].CookedValue

For VMs running on previous versions of Windows 2008, or those not using the dynamic memory feature, you can monitor the memory usage inside the VM itself using the same counters as the host.

Virtual Machines count
This command below will gauge the number of VMs that are currently running or turned off.

(get-counter '\Hyper-V Virtual Machine Summary\Running').CounterSamples[0].CookedValue
(get-counter '\Hyper-V Virtual Machine Summary\Turned Off').CounterSamples[0].CookedValue

Once you have established a baseline, you will be able to set thresholds and alerts on the charted values, as we have spoken about in previous articles.  If thresholds are exceeded frequently for a particular resource, you will have to plan for making available more hardware resource such as moving some VHDs on other physical disks, adding processors or network adapters.
For more on monitoring Hyper-V you can also read the following articles:

 

Creating a page with the Custom Monitors

In order to interact with Monitis API, you have to first request a Token to be used in the following calls, this is easily done via the command below:

$url = "http://www.monitis.com/api?action=authToken&apikey=" + $apiKey + "&secretkey=" + $secretKey
$wc = new-object net.webclient
$resp = $wc.DownloadString($url).ToString()
$pos = $resp.IndexOf(":") + 2
$token = $resp.Substring($pos, $resp.Length - $pos - 2)

Then we will add a page that contains all our Custom Monitors:

$nvc = new-object System.Collections.Specialized.NameValueCollection
$nvc.Add('apikey', $apikey)
$nvc.Add('validation', 'token')
$nvc.Add('authToken', $token)
$nvc.Add('timestamp', (get-date).touniversaltime().ToString("yyyy-MM-dd HH:mm:ss"))
$nvc.Add('action', 'addPage')
$nvc.Add('title', 'Hyper-V')
$nvc.Add('columnCount', '2')

$wc = new-object net.webclient
$wc.Headers.Add("Content-Type", "application/x-www-form-urlencoded")
$resp = $wc.UploadValues('http://www.monitis.com/api', $nvc)
$resp = [text.encoding]::ascii.getstring($resp)
$pos = $resp.IndexOf("pageId") + 8
$pageID = $resp.Substring($pos, $resp.Length - $pos - 2)

Since you’re adding several Custom Monitors, the code can be optimized using a function that creates the Custom Monitor and adds it to the page. The command is:

function AddCustMon([string] $name, [string] $monitorParams, [string] $resultParams, [string] $row, [string] $column) {
  Write-Host "Adding Custom Monitor " $name
  $nvc = new-object System.Collections.Specialized.NameValueCollection
  $nvc.Add('apikey', $apikey)
  $nvc.Add('validation', 'token')
  $nvc.Add('authToken', $token)
  $nvc.Add('timestamp', (get-date).touniversaltime().ToString("yyyy-MM-dd HH:mm:ss"))
  $nvc.Add('action', 'addMonitor')
  $nvc.Add('monitorParams', $monitorParams)
  $nvc.Add('resultParams', $resultParams)
  $nvc.Add('name', $name )
  $nvc.Add('tag', 'Hyper-V' )

  $wc = new-object net.webclient
  $wc.Headers.Add("Content-Type", "application/x-www-form-urlencoded")
  $resp = $wc.UploadValues('http://www.monitis.com/customMonitorApi', $nvc)
  $resp = [text.encoding]::ascii.getstring($resp)
  $pos = $resp.IndexOf("data") + 6
  $testID = $resp.Substring($pos, $resp.Length - $pos - 1)

  write-host "Adding test " $name " to the page"
  $nvc = new-object System.Collections.Specialized.NameValueCollection
  $nvc.Add('apikey', $apikey)
  $nvc.Add('validation', 'token')
  $nvc.Add('authToken', $token)
  $nvc.Add('timestamp', (get-date).touniversaltime().ToString("yyyy-MM-dd HH:mm:ss"))
  $nvc.Add('action', 'addPageModule')
  $nvc.Add('moduleName', 'CustomMonitor')
  $nvc.Add('pageId', $pageID)
  $nvc.Add('column', $column )
  $nvc.Add('row', $row )
  $nvc.Add('dataModuleId', $testID)

  $wc = new-object net.webclient
  $wc.Headers.Add("Content-Type", "application/x-www-form-urlencoded")
  $resp = $wc.UploadValues('http://www.monitis.com/api', $nvc)
}

Then Monitis calls the function, once per Custom Monitor:
AddCustMon ‘VM1 network transferred bytes per second’ ‘Network:Network utilization:Bytes/sec:3:false;;’ ‘sent:Sent:N%2FA:2;received:Received:N%2FA:2;’ ’3′ ’2′

Uploading Values

Once the page and the Custom Monitors are created, we can upload values into them.
First you will have to request a Token as explained above.  In order to upload values into custom monitors we have to know their assigned IDs and load them into a variable in order to avoid any further calls and improve performances.

$tag = 'Hyper-V'
$url = 'http://www.monitis.com/customMonitorApi?action=getMonitors&apikey=' + $apiKey + "&tag=" + $tag + "&output=xml"
$wc = new-object net.webclient
$resp = $wc.DownloadString($url).ToString()

$monitors = new-object "System.Xml.XmlDocument"
$monitors.LoadXml($resp)

Now the MonitorID can be found quickly using a function:

function FindMonitor([string] $name) {
  foreach ($node in $monitors.monitors.childnodes) {
    if ($node.name -eq $name) {
      return $node.id
    }
  }
}

Since we will have to upload values for several Custom Monitors, another function will also be useful to improve the efficiency:

function AddResult() {
  $nvc = new-object System.Collections.Specialized.NameValueCollection
  $nvc.Add('apikey', $apikey)
  $nvc.Add('validation', 'token')
  $nvc.Add('authToken', $token)
  $nvc.Add('timestamp', ((get-date).touniversaltime().ToString("yyyy-MM-dd HH:mm:ss").ToString()))
  $nvc.Add('action', 'addResult')
  $nvc.Add('monitorId', $monitorID)
  $nvc.Add('checktime', ([int][double]::Parse((get-date((get-date).touniversaltime()) -UFormat %s))).ToString() + '000')
  $nvc.Add('results', $results)

  $wc = new-object net.webclient
  $wc.Headers.Add("Content-Type", "application/x-www-form-urlencoded")
  $resp = $wc.UploadValues('http://www.monitis.com/customMonitorApi', $nvc)
  [text.encoding]::ascii.getstring($resp)
}

Now we can gather the values we need from Performance counter and upload them using few lines of code:

$monitorID = FindMonitor "VM1 percent processor utilization"
$value1 = (get-counter '\Hyper-V Hypervisor Virtual Processor(XPHV:Hv VP 0)\% Total Run Time').CounterSamples[0].CookedValue
$value2 = (get-counter '\Hyper-V Hypervisor Virtual Processor(XPHV:Hv VP 0)\% Guest Run Time').CounterSamples[0].CookedValue
$results = "guest:" + $value2 + ";total:" + $value1 + ";"
AddResult

You can find the full source code here.

After letting the monitors run for a while your console will look like this:

We hope that this article helps you understand how we monitor Hyper-V using PowerShell. Stay tuned for more articles showcasing even more knowledge about monitoring using Monitis!

For Monitis free signup click here.

Related links:

Hovhannes Avoyan

About Hovhannes Avoyan

Monitis CEO – Hovhannes is an international entrepreneur with a recognized and respected reputation in the high tech industry. His technical expertise, combined with his drive to build the best business/product, has positioned him as a visionary international extension of Silicon Valley.

Web & Cloud
Monitoring