Pretpostavljam da ste se svi ponekad zapitali kako je moguće pratiti prosječne statistike iskorištenosti sustava na kojem Vam se vrte hyper-v virtualne mašine. Jedan moj dragi kolega je stavio zanimljivi link Facebook o jednom gospodinu koji piše razne skripte za provjeru statusa sustava. Te Vam u nastavku iznosim jednu od skripti.
Skripta je preuzeta s Ben Armstrong blog-a i prerađena za vlastite potrebe. Kako bi skripta uspješno radilo prvo je potrebno na Vašem Hyper-v hostu upaliti određene servise za svaku pojedinu virtualnu mašinu.
Kako biste upalili mjerenje potrošnje resursa za pojedinu virtualnu mašinu potrebno je iz PowerShell-a pokrenuti:
Get-VM <virtual machine name> | Enable-VMResourceMetering
ili za sve virtualne mašine na jednom hostu:
Get-VM | Enable-VMResourceMetering
Poželjno je podesiti vremenski interval za uzimanje uzoraka. Sto stavite kraci vremenski interval to će performanse stroja biti manje. Poželjno je staviti interval svakih 1 sat, a u slučaju većeg opterećenja cak i svaka 2 sata. Podešavanje se izvodi PowerShell komandom:
Set-VMHost –ComputerName <host server name> -ResourceMeteringSaveInterval <HH:MM:SS>
Prikaz koji će se generirati nakon pokretanja skripte izgledati će kao u nastavku, a šalje se svaki dan mailom u određeno vrijeme putem windows task schedulara.
Primjer skripte koja izgleda ovako:
# Variables
$filedate = get-date
$computer = gc env:computername
$metricsData = get-vm | measure-vm
$tableColor = "WhiteSmoke"
$errorColor = "Red"
$warningColor = "Yellow"
$FromEmail = "email@email.org"
$ToEmail = "email@email.org"
# Establish Connection to SMTP server
$smtpServer = "smtp.yourISP.com"
#$smtpCreds = new-object Net.NetworkCredential("yourUsername", "YourPassword") #SMTP Authentication if not using Exchange
$smtp = new-object Net.Mail.SmtpClient($smtpServer, 25) #Exchange FQDN
$smtp.UseDefaultCredentials = $false
#$smtp.Credentials = $smtpCreds
# HTML Style Definition
$message = "<!DOCTYPE html PUBLIC`"-//W3C//DTD XHTML 1.0 Strict//EN`" `"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd`">"
$message = "<html xmlns=`"http://www.w3.org/1999/xhtml`"><body>"
$message = "<style>"
$message = $message + "TABLE{border-width:2px;border-style: solid;border-color: #C0C0C0 ;border-collapse: collapse;width: 100%}"
$message = $message + "TH{border-width: 2px;padding: 0px;border-style: solid;border-color: #C0C0C0 ;text-align: left}"
$message = $message + "TD{border-width: 2px;padding: 0px;border-style: solid;border-color: #C0C0C0 ;text-align: left}"
$message = $message + "TD{border-width: 2px;padding: 0px;border-style: solid;border-color: #C0C0C0 ;text-align: left}"
$message = $message + "H1{font-family:Calibri;}"
$message = $message + "H2{font-family:Calibri;}"
$message = $message + "Body{font-family:Calibri;}"
$message = $message + "</style>"
# Title
$message = $message + "<h2>Data for Hyper-V Server '$($computer)' : $($filedate)</h2>"
# EventLog
$message = $message + "<style>TH{background-color:$($errorColor)}TR{background-color:$($tableColor)}</style>"
$message = $message + "<B>Parent EventLog</B> <br> <br>"
$message = $message + "Errors: <br>" + ((Get-EventLog system -after (get-date).AddHours(-24) -entryType Error) | `
Select-Object @{Expression={$_.InstanceID};Label="ID"}, `
@{Expression={$_.Source};Label="Source"}, `
@{Expression={$_.Message};Label="Message"} `
| ConvertTo-HTML -Fragment) `
+ " <br>"
$message = $message + "<style>TH{background-color:$($warningColor)}TR{background-color:$($tableColor)}</style>"
$message = $message + "Warnings: <br>" + ((Get-EventLog system -after (get-date).AddHours(-24) -entryType Warning) | `
Select-Object @{Expression={$_.InstanceID};Label="ID"}, `
@{Expression={$_.Source};Label="Source"}, `
@{Expression={$_.Message};Label="Message"} `
| ConvertTo-HTML -Fragment) `
+ " <br>"
# Hyper-V EventLog
$message = $message + "<style>TH{background-color:$($errorColor)}TR{background-color:$($tableColor)}</style>"
$message = $message + "<B>Hyper-V EventLog</B> <br> <br>"
$message = $message + "Errors: <br>" + ((Get-WinEvent -FilterHashTable @{LogName ="Microsoft-Windows-Hyper-V*"; StartTime = (Get-Date).AddDays(-1); Level = 2}) | `
Select-Object @{Expression={$_.InstanceID};Label="ID"}, `
@{Expression={$_.Source};Label="Source"}, `
@{Expression={$_.Message};Label="Message"} `
| ConvertTo-HTML -Fragment) `
+ " <br>"
$message = $message + "<style>TH{background-color:$($warningColor)}TR{background-color:$($tableColor)}</style>"
$message = $message + "Warnings: <br>" + ((Get-WinEvent -FilterHashTable @{LogName ="Microsoft-Windows-Hyper-V*"; StartTime = (Get-Date).AddDays(-1); Level = 3}) | `
Select-Object @{Expression={$_.InstanceID};Label="ID"}, `
@{Expression={$_.Source};Label="Source"}, `
@{Expression={$_.Message};Label="Message"} `
| ConvertTo-HTML -Fragment) `
+ " <br>"
# VM Health
$message = $message + "<style>TH{background-color:Indigo}TR{background-color:$($errorColor)}</style>"
$message = $message + "<B>Virtual Machine Health</B> <br> <br>"
$message = $message + "Virtual Machine Health: <br>" + ((Get-VM | `
Select-Object @{Expression={$_.Name};Label="Name"}, `
@{Expression={$_.State};Label="State"}, `
@{Expression={$_.Status};Label="Operational Status"}, `
@{Expression={$_.UpTime};Label="Up Time"} `
| ConvertTo-HTML -Fragment) `
| %{if($_.Contains("<td>Operating normally</td>")){$_.Replace("<tr><td>", "<tr style=`"background-color:$($warningColor)`"><td>")}else{$_}} `
| %{if($_.Contains("<td>Running</td><td>Operating normally</td>")){$_.Replace("<tr style=`"background-color:$($warningColor)`"><td>", "<tr style=`"background-color:$($tableColor)`"><td>")}else{$_}}) `
+ " <br>"
# VM Replication Health
$message = $message + "<style>TH{background-color:Indigo}TR{background-color:$($errorColor)}</style>"
$message = $message + "<B>Virtual Machine Replication Health</B> <br> <br>"
$message = $message + "Virtual Machine Replication Health: <br>" + ((Get-VM | `
Select-Object @{Expression={$_.Name};Label="Name"}, `
@{Expression={$_.ReplicationState};Label="State"}, `
@{Expression={$_.ReplicationHealth};Label="Health"}, `
@{Expression={$_.ReplicationMode};Label="Mode"} `
| ConvertTo-HTML -Fragment) `
| %{if($_.Contains("<td>Replicating</td><td>Normal</td>")){$_.Replace("<tr><td>", "<tr style=`"background-color:$($tableColor)`"><td>")}else{$_}}) `
+ " <br>"
# Storage Health
$message = $message + "<style>TH{background-color:DarkGreen}TR{background-color:$($errorColor)}</style>"
$message = $message + "<B>Storage Health</B> <br> <br>"
$message = $message + "Physical Disk Health: <br>" + ((Get-PhysicalDisk | `
Select-Object @{Expression={$_.FriendlyName};Label="Physical Disk Name"}, `
@{Expression={$_.DeviceID};Label="Device ID"}, `
@{Expression={$_.OperationalStatus};Label="Operational Status"}, `
@{Expression={$_.HealthStatus};Label="Health Status"}, `
@{Expression={"{0:N2}" -f ($_.Size / 1073741824)};Label="Size (GB)"} `
| ConvertTo-HTML -Fragment) `
| %{if($_.Contains("<td>OK</td><td>Healthy</td>")){$_.Replace("<tr><td>", "<tr style=`"background-color:$($tableColor)`"><td>")}else{$_}}) `
+ " <br>"
$message = $message + "Storage Pool Health: <br>" + ((Get-StoragePool | `
where-object {($_.FriendlyName -ne "Primordial")} | `
Select-Object @{Expression={$_.FriendlyName};Label="Storage Pool Name"}, `
@{Expression={$_.OperationalStatus};Label="Operational Status"}, `
@{Expression={$_.HealthStatus};Label="Health Status"} `
| ConvertTo-HTML -Fragment) `
| %{if($_.Contains("<td>OK</td><td>Healthy</td>")){$_.Replace("<tr><td>", "<tr style=`"background-color:$($tableColor)`"><td>")}else{$_}}) `
+ " <br>"
$message = $message + "Virtual Disk Health: <br>" + ((Get-VirtualDisk | `
Select-Object @{Expression={$_.FriendlyName};Label="Virtual Disk Name"}, `
@{Expression={$_.OperationalStatus};Label="Operational Status"}, `
@{Expression={$_.HealthStatus};Label="Health Status"} `
| ConvertTo-HTML -Fragment) `
| %{if($_.Contains("<td>OK</td><td>Healthy</td>")){$_.Replace("<tr><td>", "<tr style=`"background-color:$($tableColor)`"><td>")}else{$_}}) `
+ " <br>"
# VM Metrics
$message = $message + "<style>TH{background-color:blue}TR{background-color:$($tableColor)}</style>"
$message = $message + "<B>Virtual Machine Utilization Report</B> <br> <br> "
$message = $message + "CPU utilization data: <br>" + ($metricsData | `
select-object @{Expression={$_.VMName};Label="Virtual Machine"}, `
@{Expression={$_.AvgCPU};Label="Average CPU Utilization (MHz)"} `
| ConvertTo-HTML -Fragment) `
+" <br>"
$message = $message + "Memory utilization data: <br>" + ($metricsData | `
select-object @{Expression={$_.VMName};Label="Virtual Machine"}, `
@{Expression={$_.AvgRAM};Label="Average Memory (MB)"}, `
@{Expression={$_.MinRAM};Label="Minimum Memory (MB)"}, `
@{Expression={$_.MaxRAM};Label="Maximum Memory (MB)"} `
| ConvertTo-HTML -Fragment) `
+" <br>"
$message = $message + "Network utilization data: <br>" + ($metricsData | `
select-object @{Expression={$_.VMName};Label="Virtual Machine"}, `
@{Expression={"{0:N2}" -f (($_.NetworkMeteredTrafficReport | where-object {($_.Direction -eq "Inbound")}`
| measure-object TotalTraffic -sum).sum / 1024)};Label="Inbound Network Traffic (GB)"}, `
@{Expression={"{0:N2}" -f (($_.NetworkMeteredTrafficReport | where-object {($_.Direction -eq "Outbound")} `
| measure-object TotalTraffic -sum).sum / 1024)};Label="Outbound Network Traffic (GB)"} `
| ConvertTo-HTML -Fragment) `
+" <br>"
$message = $message + "Disk utilization data: <br>" + ($metricsData | `
select-object @{Expression={$_.VMName};Label="Virtual Machine"}, `
@{Expression={"{0:N2}" -f ($_.TotalDisk / 1024)};Label="Disk Space Used (GB)"} `
| ConvertTo-HTML -Fragment) `
+" <br>"
$message = $message + "Metering Duration data: <br>" + ($metricsData | `
select-object @{Expression={$_.VMName};Label="Virtual Machine"}, `
@{Expression={$_.MeteringDuration};Label="Metering data duration"} `
| ConvertTo-HTML -Fragment) `
+" <br>"
# Reset metrics
get-vm | Reset-VMResourceMetering
get-vm | Enable-VMResourceMetering
$message = $message + "</body></html>"
$email = new-object Net.Mail.MailMessage
$email.Subject = "Hyper-V Server Report: $($filedate)"
$email.From = new-object Net.Mail.MailAddress($FromEmail)
$email.IsBodyHtml = $true
$email.Body = $message
$email.To.Add($ToEmail)
# Send Email
$smtp.Send($email)
U prilogu se nalazi skripta ako ju želite preuzeti u .ps1 formatu.
Attachment: DailyStatsReport