VMware Cloud Community
ehermouet44
Contributor
Contributor
Jump to solution

Powercli script mem, cpu, disk, uptime

Hi all

first tks for this forum. i just see that very good tool exist -> powercli Smiley Happy

i try to do somethings.

first i want per vm the % of uptime per vm

and the average of cpu usage, mem usage etc... from last year.

i can do this per script but i don't found how.

tks for your help

0 Kudos
35 Replies
ehermouet44
Contributor
Contributor
Jump to solution

function Get-VMUptime {
<# 
.SYNOPSIS  Calculate the VM uptime percentage 
.DESCRIPTION The function will calculate the uptime
    percentage for a VM for a given period of time 
.NOTES  Author:  Luc Dekens 
.PARAMETER VM
    One or more virtual machines. This parameter accepts
    pipeline input. 
.PARAMETER Start
    Start of the interval over which the uptime percentage
    shall be calculated. THe default is 7 days ago. 
.PARAMETER Finish
    End of the interval. The default is 'now'. 
.EXAMPLE
    PS> Get-VMUptime -VM MyVM
.EXAMPLE
   PS> Get-VM VM | Get-VMUptime -Start $start
#>
  param(
    [CmdletBinding()]
    [Parameter(
      Position=0,
      Mandatory=$true,
      ValueFromPipeline=$true,
      ValueFromPipelineByPropertyName=$true
    )]
    [PSObject[]]$VM,
    [Datetime]$Start = ((Get-Date).AddDays(-7)),
    [Datetime]$Finish = (Get-Date)
  )
  process {
    $extraStart = $Start.AddDays(-1)
    Get-Stat -Entity $VM -Stat "sys.uptime.latest" -Start $extraStart -Finish $Finish -ErrorAction SilentlyContinue |
    Group-Object -Property {$_.Entity.Name} | %{
      if($_.Group){
        $totalUptime = 0
        $intervalDuration = $_.Group[0].IntervalSecs
        $numberOfSamples = $_.Count - (86400 / $intervalDuration)
        $startInterval = $_.Group[$numberOfSamples - 1].Timestamp - (New-TimeSpan -Seconds $intervalDuration)
        $uptime = New-TimeSpan -Seconds $_.Group[0].Value
        if(($_.Group[0].Timestamp - $uptime) -le $startInterval){
          $totalUptime = $numberOfSamples * $intervalDuration
        }
        else{
          $i = [math]::Floor($_.Group[0].Value/$intervalDuration)
          $totalUptime = $_.Group[0].Value
          $i++
          while($i -lt $numberOfSamples){
            if(0,1 -notcontains $_.Group[$i].Value){
              $j = $i + [math]::Floor($_.Group[$i].Value/$intervalDuration) + 1
              if($j -le $numberOfSamples){
                $totalUptime += $_.Group[$i].Value
                $i = $j++
              }
              else{
                $partialIntervalValue = $_.Group[$i].Value - $_.Group[$i + 1].Value
                $completeIntervals = $numberOfSamples - $i - 1
                $fullIntervalsValue = $completeIntervals * $intervalDuration
                $totalUptime += ($fullIntervalsValue + $partialIntervalValue)
                $i = $j
              }
            }
          }
        }
        New-Object PSObject -Property @{
          VM = $_.Name
          Uptime = [math]::Round(($totalUptime / ($numberOfSamples * $intervalDuration) * 100),2)
          Unit = "percent"
          Start = $startInterval
          Finish = $_.Group[0].Timestamp
        }
      }
      else{
        New-Object PSObject -Property @{
          VM = $_.Name
          Uptime = "no data"
          Unit = ""
          Start = $Start
          Finish = $Finish
        }
      }
    }
  }
}
i copy this from your website. I m connect to my vcenter on powercli
0 Kudos
LucD
Leadership
Leadership
Jump to solution

That is indeed the function, but you need to call the function to make it return some results.

That is what the Sample Usage section in my blog post shows.

For example:

$vm = Get-VM MyVM

Get-VMUptime -VM $vm

will call the function for the VM called MyVM, and the results will be displayed on the screen.

Practically you can do the following:

  • store the function in a file with the type .ps1, for example get-vmuptime.ps1
  • now dot-source that file, this way PowerShell will read the file and "know" the function. There is a blank between those 2 dots !

. ./get-vmuptime.ps1

  • You can now call the function. From the PowerCLI promtp do the following

$vm = Get-VM -Name One-Of-Your-VM

Get-VMUptime -VM $vm

  • This should show you the uptime data on screen

Let me know if that works


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

0 Kudos
ehermouet44
Contributor
Contributor
Jump to solution

Get-VMUptime work on esx 4.1 ? because powercli said that this command is not know command.

0 Kudos
LucD
Leadership
Leadership
Jump to solution

That is why you need to do the dot-sourcing of the .ps1 file that contains the function definition first.

Like I said that way PowerShell "knows" the function.

Once the function is known, you can call it.


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

0 Kudos
ehermouet44
Contributor
Contributor
Jump to solution

haaa i understand Smiley Happy tks

i want to do some complex things.

in my script i want to specify interval date except day not work and time work.

for exemple from 8h to 18h and not the sunday for last month Smiley Happy very complex i thing.

do you know thta i can build script like that ?

0 Kudos
LucD
Leadership
Leadership
Jump to solution

The Get-VMUptime function returns the start and finish of each interval for which it has data.

You can check if your custom intervals fall within that timerange.

To produce reports for specific time ranges and specific days you can have a look at my PowerCLI & vSphere statistics – Part 2 – Come together post. It contains a sample script to work with a Custom sampling period.


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

0 Kudos
ehermouet44
Contributor
Contributor
Jump to solution

2h that i search

but 0 entry in my file

i try like this

$vm = Get-VM -Name myvm
$todayMidnight = (Get-Date -Hour 0 -Minute 0 -Second 0).AddMinutes(-1)
$workingDays = "Monday","Tuesday","Wednesday","Thursday","Friday"
$dayStart = New-Object DateTime(1,1,1,7,30,0)     # 07:30 AM
$dayEnd = New-Object DateTime(1,1,1,17,30,0)      # 05:30 PM
$stats = Get-VMUptime -VM $vm -Start $todayMidnight.AddDays(-14) -Finish $todayMidnight.AddDays(-7)
$report = $stats | Where-Object {
$workingDays -contains $_.Timestamp.DayOfWeek -and
$_.Timestamp.TimeOfDay -gt $dayStart.TimeOfDay -and
$_.Timestamp.TimeOfDay -lt $dayEnd.TimeOfDay
}
$report | Export-Csv "C:\BusinessHours-cpu.csv" -NoTypeInformation -UseCulture

tks advance for your help

0 Kudos
LucD
Leadership
Leadership
Jump to solution

The Get-VMUptime function doesn't return the same objects as the Get-Stat cmdlet.

You would have to test if the special intervals you have fall inside the timespan returned by the function.


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

0 Kudos
ehermouet44
Contributor
Contributor
Jump to solution

like that

$vm = Get-VM -Name Clone-SPEXCHANGE
$todayMidnight = (Get-Date -Hour 0 -Minute 0 -Second 0).AddMinutes(-1)
$workingDays = "Monday","Tuesday","Wednesday","Thursday","Friday"
$dayStart = New-Object DateTime(1,1,1,7,30,0)     # 07:30 AM
$dayEnd = New-Object DateTime(1,1,1,17,30,0)      # 05:30 PM
Get-VMUptime -VM $vm -Start $todayMidnight.AddDays(-14) -Finish $todayMidnight.AddDays(-7)
$stats = Get-VMUptime -VM $vm -Start $todayMidnight.AddDays(-14) -Finish $todayMidnight.AddDays(-7)
$report = $stats | Where-Object {
$workingDays -contains $_.Timestamp.DayOfWeek -and
$_.Timestamp.TimeOfDay -gt $dayStart.TimeOfDay -and
$_.Timestamp.TimeOfDay -lt $dayEnd.TimeOfDay
}
$report | Export-Csv "C:\BusinessHours-cpu2.csv" -NoTypeInformation -UseCulture
i can see my value on shell, but nothing on exported file.:smileyconfused:
0 Kudos
ehermouet44
Contributor
Contributor
Jump to solution

Luc i found your very good post

$esxName = "192.168.1.20"
$tgtAdapters = "vmhba33","vmhba34"
$metrics = "disk.deviceLatency.average","disk.kernelLatency.average",
"disk.queueLatency.average","disk.commandsAborted.summation",
"disk.busResets.summation"
$esxImpl = Get-VMHost -Name $esxName
$esx = $esxImpl | Get-View
$endDate = Get-Date
$startDate = $endDate.AddHours(-1)
# # Find active instances per selected adapter
$instances = @{}
$instancesFilter = @()
foreach($adapter in $tgtAdapters){
$adapterInstances = @()
$adapterKey = ($esx.Config.StorageDevice.HostBusAdapter | where {$adapter -eq $_.Device}).Key
foreach($lun in $esx.Config.StorageDevice.MultipathInfo.Lun){
foreach($path in $lun.Path){
if($path.Adapter -eq $adapterKey -and $path.PathState -eq "active"){
foreach($scsiLun in $esx.Config.StorageDevice.ScsiLun){
if($scsiLun.Key -eq $lun.lun){
$adapterInstances += $scsiLun.CanonicalName
$instancesFilter += $scsiLun.CanonicalName
}
}
}
}
}
$instances[$adapter] = $adapterInstances
}
# Get statistics for instances
$stats = Get-Stat -Entity $esxImpl -Stat $metrics -Start $startDate -Finish $endDate | `
where {$instancesFilter -contains $_.Instance}
# Create the reporting array
$hbaTab = @{}
$stats | %{
# Determine HBA-name based on instance
$instance = $_.Instance
$instances.GetEnumerator() | %{
if($_.Value -contains $instance){$currentHba = $_.Name}
}
# Gethash table for adapter
if($hbaTab.ContainsKey($currentHba)){
$timeTab = $hbaTab[$currentHba]
}
else{
$timeTab = @{}
}
# Check if there is a row for this timestamp
if($timeTab.ContainsKey($_.Timestamp)){
$row = $timeTab[$_.Timestamp]
}
else{
$row = New-Object PSObject -Property @{
Time = $_.Timestamp
Interval = 0
GAVG = 0
DAVG = 0
KAVG = 0
QUED = 0
ABRT = 0
RESET = 0
}
}
$row.Interval = $_.IntervalSecs
$value = $_.Value
switch($_.MetricId){
"disk.deviceLatency.average"{$row.DAVG += $Value}
"disk.kernelLatency.average"{$row.KAVG += $Value}
"disk.queueLatency.average"{$row.QUED += $Value}
"disk.commandsAborted.summation"{$row.ABRT += $Value}
"disk.busResets.summation"{$row.RESET += $Value}
}
$timeTab[$_.Timestamp] = $row
$hbaTab[$currentHba] = $timeTab
}
$hbaTab.GetEnumerator() | %{
$_.Value.GetEnumerator() | %{
$_.Value.GAVG = $_.Value.DAVG + $_.Value.KAVG
$_.Value.ABRT /= $_.Value.Interval
$_.Value.RESET /= $_.Value.Interval
}
$_.Value.Values | Sort-Object -Property Time | `
Export-Csv ("C:\IO-stat-" + $esxName.Split(".")[0] + "-" + $_.Name + ".csv") -NoTypeInformation -UseCulture
}

it's the same that my other script, i try something to integer works days but i don't found how. can you help me please ?

0 Kudos
LucD
Leadership
Leadership
Jump to solution

This script uses metrics returned by Get-Stat, so you could update the Where-clause, that now only check the instance, to also check the timespans (like you already tried to do in the previous script).


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

0 Kudos
ehermouet44
Contributor
Contributor
Jump to solution

OK Luc

but how to know metric for get-* ?

tks advance

0 Kudos
LucD
Leadership
Leadership
Jump to solution

Perhaps I don't understand your question correctly, but the counters are defined in the $metrics variable in that script.


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

0 Kudos
ehermouet44
Contributor
Contributor
Jump to solution

$stats = Get-VMUptime -VM $vm -Start $todayMidnight.AddDays(-30) -Finish $todayMidnight.AddDays(-1)
$report = $stats | Where-Object {
$workingDays -contains $_.Timestamp.DayOfWeek -and
$_.Timestamp.TimeOfDay -gt $dayStart.TimeOfDay -and
$_.Timestamp.TimeOfDay -lt $dayEnd.TimeOfDay
}
$report | Export-Csv "C:\scriptvm\uptime\uptimecsv.csv" -NoTypeInformation -UseCulture

here is a part of script that not work. but - >
$stats = Get-VMUptime -VM $vm -Start $todayMidnight.AddDays(-30) -Finish $todayMidnight.AddDays(-1)
works

the script is here

$vm = Get-VM -Name Clone-SPEXCHANGE
$todayMidnight = (Get-Date -Hour 0 -Minute 0 -Second 0).AddMinutes(-1)
$workingDays = "Monday","Tuesday","Wednesday","Thursday","Friday"
$dayStart = New-Object DateTime(1,1,1,7,30,0)     # 07:30 AM
$dayEnd = New-Object DateTime(1,1,1,17,30,0)      # 05:30 PM
Get-VMUptime -VM $vm -Start $todayMidnight.AddDays(-30) -Finish $todayMidnight.AddDays(-1)
$stats = Get-VMUptime -VM $vm -Start $todayMidnight.AddDays(-30) -Finish $todayMidnight.AddDays(-1)
$report = $stats | Where-Object {
$workingDays -contains $_.Timestamp.DayOfWeek -and
$_.Timestamp.TimeOfDay -gt $dayStart.TimeOfDay -and
$_.Timestamp.TimeOfDay -lt $dayEnd.TimeOfDay
}
$report | Export-Csv "C:\scriptvm\uptime\uptimecsv.csv" -NoTypeInformation -UseCulture

my csv file is empty but on my powershell i can see my uptime for time timestamp. $report is only to export no ?
0 Kudos
LucD
Leadership
Leadership
Jump to solution

Sorry, but I have the impression you are trying to compare apples with pears.

The Get-VMUptime function returns 1 or more objects that each have a Start and Finish property that hold a DateTime value and a percentage indicating how much time in between Start and Finish the VM was up..

For example, for a VM that hasn't been down for the requested interval, you will get back 1 object. Something like this

uptime-object.png

You now want to check if specific time intervals for specific days are present in this interval.

That should be possible, you can check if your interval falls within the interval delimited by Start and Finish.

But I'm not sure how you want to convert the uptime percentage.


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

0 Kudos
ehermouet44
Contributor
Contributor
Jump to solution

that i want it's that script show me % of uptime between the start and end time in the works time of users ->

$workingDays = "Monday","Tuesday","Wednesday","Thursday","Friday"
$dayStart = New-Object DateTime(1,1,1,7,30,0)     # 07:30 AM
$dayEnd = New-Object DateTime(1,1,1,17,30,0)      # 05:30 PM

so this is work but i want to export this on csv file. it's here that not works.

tks Luc

0 Kudos