VMware Cloud Community
madpro
Enthusiast
Enthusiast

Get-vievent to extract some user data from vsphere

HI there

I am trying to get some info from a list of vms in a folder.

I want to find out

  • the last power on time of the vm
  • who last powered it on

I have the following script but it does not get all the data i need.

The end result I want is all the info in a json file, which I will be using elsewhere.

# Connect to the vCenter Server
Connect-VIServer -Server 'vcenter_ip' -User 'username' -Password 'password'

# Get the VMs in the folder
$vms = Get-Folder 'vmfolder' | Get-VM

# Create an array to hold the data
$data = @()

# For each VM, get the events
foreach ($vm in $vms) {
$powerOnEvent = Get-VIEvent -Entity $vm | Where-Object { $_.GetType().Name -eq "VmPoweredOnEvent" } | Select-Object -First 1
$resetEvent = Get-VIEvent -Entity $vm | Where-Object { $_.GetType().Name -eq "VmResetEvent" } | Select-Object -First 1

# Add the VM name and the event information to the data array
$data += New-Object PSObject -Property @{
VMName = $vm.Name
LastPoweredOnDate = $powerOnEvent.CreatedTime
PowerOnVMUser = $powerOnEvent.UserName
LastResetDate = $resetEvent.CreatedTime
ResetUserName = $resetEvent.UserName
}
}

# Output the data to a JSON file
$data | ConvertTo-Json | Set-Content 'data.json'

# Disconnect from the vCenter Server
Disconnect-VIServer -Server 'vcenter_ip' -Confirm:$false

 

Can anyone advise why this is not working please?

Thanks!

0 Kudos
7 Replies
LucD
Leadership
Leadership

Not sure why you are doing the Select-Object -First 1 after the Get-VIEvent cmdlets.
If the events come in chronological order, you will only begetting the oldest event.

Also, you are doing a Get-VIEvent without the MaxSamples parameter, which means there will only be 100 (the default for MaxSamples) events returned.


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

0 Kudos
madpro
Enthusiast
Enthusiast

Thanks LucD,

I have changed the my code as advised and now I get some results returned, VMname and lastpoweredondate but not the poweronvmuser...

0 Kudos
LucD
Leadership
Leadership

That is a known issue that the UserName field is empty sometimes.
An alternative is to search for the corresponding TaskEvent (use the ChainId in the poweredon event and find the event with the same Key).
The TaskEvent often has the UserName in that case.


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

0 Kudos
madpro
Enthusiast
Enthusiast

Ok, thanks LucD, I will try that

0 Kudos
LucD
Leadership
Leadership

I would do something like this

Note1: that event should be VMware.Vim.VmResettingEvent I assume
Note2: I use Group-Object to minimise the number of calls to Get-VIEvent, which is a costly cmdlet  (in execution time)
Note3: in this snippet I looked back 1 hour, you can adapt as required. But be aware that going back far in the past will make the Get-VIEvent cmdlet run for a very long time

 

# Connect to the vCenter Server
Connect-VIServer -Server 'vcenter_ip' -User 'username' -Password 'password'

# Get the VMs in the folder
$vms = Get-Folder 'vmfolder' | Get-VM

# Create an array to hold the data
$data = @()

Get-VIEvent -Entity $vms -MaxSamples ([int]::MaxValue) -Start (Get-Date).AddHours(-1) |
Group-Object -Property {$_.Vm.Name} |
ForEach-Object -Process {
  $reset = $_.Group | Where{$_ -is [VMware.Vim.VmResettingEvent]} | Sort-Object -Property CreatedTime -Descending | Select -First 1
  $powerOn = $_.Group | Where-Object { $_ -is [VMware.Vim.VmPoweredOnEvent] } | Sort-Object -Property CreatedTime -Descending | Select-Object -First 1
  if ($reset) {
    $rTask = $_.Group | Where-Object { $_.Key -eq $reset.ChainId }
  }
  if ($poweredOn) {
    $poTask = $_.Group | where{$_.Key -eq $poweredOn.ChainId}
  }
  $data += New-Object PSObject -Property @{
    VMName = $poweredOn.Vm.Name
    LastPoweredOnDate = $powerOn.CreatedTime
    PowerOnVMUser = if($powerOn.UserName){$powerOn.UserName}else{$poTask.UserName}
    LastResetDate = $reset.CreatedTime
    ResetUserName = if ($reset.UserName) { $reset.UserName }else { $rTask.UserName}
  }
}

# Output the data to a JSON file
$data | ConvertTo-Json | Set-Content 'data.json'

# Disconnect from the vCenter Server
Disconnect-VIServer -Server 'vcenter_ip' -Confirm:$false

 


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

0 Kudos
madpro
Enthusiast
Enthusiast

Hi LucD

I tried the full script and the $data variable is blank, so there is no output.

I tried running just 

Get-VIEvent -Entity vmname -Start (Get-Date).AddHours(-1)

where vmname is just one of my running VMs, and this does not output anything....so I'm not sure it likes the get-date. 

I also tried 

Get-VIEvent -Entity vmname -Start (Get-Date -Format"dd/mm/yyyy" ).AddHours(-1)

 

to make sure the formatting of the date was in the correct format, and I get this error

Get-Date : Cannot bind parameter 'Date'. Cannot convert value "-Formatdd/mm/yyyy" to type "System.DateTime". Error: "String was not recognized as a valid DateTime."

 

Not sure what is going on...

0 Kudos
LucD
Leadership
Leadership

The Start (and Finish) parameter expect a DateTime object, so the object returned by Get-Date should work.
It could be that there aren't any events for that VM during that last hour.
Try increasing the duration of the interval.

Also, add the MaxSamples parameter, otherwise only 100 events will be returned.

The Get-Date with a Format string returns a String, not a DateTime object.



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

0 Kudos