Hi all,
Is there any way to monitor whether a VM has been ( or is being ) migrated by DRS via a PowerShell script?
The reason I ask is that I would like to use the Automatic DRS facility within a cluster but have any movements monitored and the VM, its Source and its Destination reported or alerted upon. In this manner I could keep our company Configuration Database up to date and thus keep the pencil pushers off my back.
I appreciate it may be simpler to run a script on a regular basis rather than have it perpetually loop waiting for a migration and thus wasting resources.
I assume that the Recent Task list needs to be searched but if anyone has any brighter ideas I would be very appreciative.
Apologies if this has been asked before and already has an answer only I have Googled this request and have yet to find any pointers.
Thanks
Brucky
Anything you see in the VI Client tasks pane will show up when you use the Get-Task cmdlet. And you can use Wait-Task to wait for completion.
Author of the upcoming book: Managing VMware Infrastructure with PowerShell
Co-Host, PowerScripting Podcast (http://powerscripting.net)
Thanks Hal,
Does this mean I have to keep cycling around with a Get-Task ?
Also how do I only filter on Migration tasks?
I have run Get-Task on a Migration task and got the following
</p></p> <p><p>PS C:\WINDOWS> get-task Success</p></p> <p><p>Name State % Complete Start Time Finish Time<br/><br/> ---- ----- ---------- ---------- -----------<br/><br/> Success 100 05:00:02 05:01:30</p></p> <p><p>
</p>
Any help would be gratefully accepted.
- Brucky
PS Love your PowerScripting Podcast ! I only found it 2 months ago but have downloaded all 33 episodes and have had a marathon catch-up - Worse than watching 24 on DVD !
Does this mean I have to keep cycling around with a Get-Task ?
Also how do I only filter on Migration tasks?
Hmm. Yeah, the task objects by themselves are next to useless. I believe you can get more data on the tasks by delving into the SDK. I don't have time to elaborate right now, but there's a buncha smart ppl in this forum.
PS Love your PowerScripting Podcast ! I only found it 2 months ago but have downloaded all 33 episodes and have had a marathon catch-up - Worse than watching 24 on DVD !
Hey, thanks! I'll let Jonathan know as well. We love getting feedback.
Author of the upcoming book: Managing VMware Infrastructure with PowerShell
Co-Host, PowerScripting Podcast (http://powerscripting.net)
And into the SDK we go...
With the HistoryCollector we can get a list of all tasks for a defined period.
In the list of tasks we have to get the tasks that have a DescriptionId that starts with Drm.
Note1: the number of days to look back is defined in the variable $days
Note2: I couldn't find a way to get all the tasks without specifying a number to the ReadNextTasks method.
I took 999 since this is normally enough for our environment but your millage can vary...
$days = 1 $tasknumber = 999 [http://Reflection.Assembly|http://Reflection.Assembly]::LoadWithPartialName("vmware.vim") $svcRef = new-object VMware.Vim.ManagedObjectReference $svcRef.Type = "ServiceInstance" $svcRef.Value = "ServiceInstance" $serviceInstance = get-view $svcRef $taskMgr = $serviceInstance.Content.TaskManager $filter = New-Object VMware.Vim.TaskFilterSpec $filter.Time = New-Object VMware.Vim.TaskFilterSpecByTime $filter.Time.beginTime = (Get-Date).AddDays(-$days) $filter.Time.timeType = "startedTime" $collectionImpl = ([http://VMware.Vim.TaskManager|http://VMware.Vim.TaskManager]$taskMgr).CreateCollectorForTasks($filter) ([http://VMware.Vim.TaskHistoryCollector|http://VMware.Vim.TaskHistoryCollector]$collectionImpl).RewindCollector $collection = ([http://VMware.Vim.TaskHistoryCollector|http://VMware.Vim.TaskHistoryCollector]$collectionImpl).ReadNextTasks($tasknumber) $collection | Where-Object {$_.DescriptionId -like "Drm*"} | Sort-Object StartTime | %{ write-host $_.StartTime $_.EntityName $_.State }
PS: I attached the script since the forum SW tends to change certain characters (i.e. square brackets)
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
Luc,
Thanks for this. It works like a charm.
Is there anyway of seeing the contents of the message so I could see which ESX hosts were the source and the targets for the migrations?
Sorry if I'm asking the earth but I am still trying to get my head around using the SDK in PowerShell.
Your help is gratefuly accepted.
- Brucky
That is possible but with a catch.
The from and to ESX hosts are not contained in the task history but in the event history.
Luckily the TaskInfo object contains the EventChainId property that points to the related events.
In any case, a good suggestion for extending the script.
Let me have a look and I'll get back to you.
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
This should do the trick.
$days = 1 $tasknumber = 999 $eventnumber = 100 [http://Reflection.Assembly|http://Reflection.Assembly]::LoadWithPartialName("vmware.vim") $svcRef = new-object VMware.Vim.ManagedObjectReference $svcRef.Type = "ServiceInstance" $svcRef.Value = "ServiceInstance" $serviceInstance = get-view $svcRef $taskMgr = $serviceInstance.Content.TaskManager $eventMgr = $serviceInstance.Content.eventManager $filter = New-Object VMware.Vim.TaskFilterSpec $filter.Time = New-Object VMware.Vim.TaskFilterSpecByTime $filter.Time.beginTime = (Get-Date).AddDays(-$days) $filter.Time.timeType = "startedTime" $collectionImpl = ([http://VMware.Vim.TaskManager|http://VMware.Vim.TaskManager]$taskMgr).CreateCollectorForTasks($filter) ([http://VMware.Vim.TaskHistoryCollector|http://VMware.Vim.TaskHistoryCollector]$collectionImpl).RewindCollector $collection = ([http://VMware.Vim.TaskHistoryCollector|http://VMware.Vim.TaskHistoryCollector]$collectionImpl).ReadNextTasks($tasknumber) $collection | Where-Object {$_.DescriptionId -like "Drm*"} | Sort-Object StartTime | %{ write-host $_.StartTime $_.EntityName $_.State $efilter = New-Object VMware.Vim.EventFilterSpec $efilter.eventChainId = $_.EventChainId $ecollectionImpl = ([http://VMware.Vim.EventManager|http://VMware.Vim.EventManager]$eventMgr).CreateCollectorForEvents($efilter) $ecollection = ([http://VMware.Vim.EventHistoryCollector|http://VMware.Vim.EventHistoryCollector]$ecollectionImpl).ReadNextEvents($eventnumber) foreach($event in $ecollection){ switch($event.GetType()){ "VMware.Vim.DrsVmMigratedEvent" { $from = $event.SourceHost.Name } "VMware.Vim.VmBeingHotMigratedEvent"{ $to = $event.DestHost.Name } } } Write-Host " From : " $from Write-Host " To : " $to }
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
Luc, You Beauty !!!!
Thank you for this. It is exactly what I needed.
I was starting to get my head around what you had done and was experimenting with the EventTaskManager but you beat me to it. I will be able to combine this script with my own emailing script to auto-update our Configuration Management Database.
Thanks again for your time and patience.
I owe you one !
- Brucky
Hi Luc,
I was looking for something along these lines when i came across your script. but i'm having a problem running it i get an error:
Cannot convert "VMware.Vim.ManagedObjectReference" to "VMware.Vim.TaskManager".
At C:\scripts\ESX-collect-tasks.ps1:17 char:52
+ $collectionImpl = (http://VMware.Vim.TaskManager$taskMgr <<<< ).CreateCollectorForTasks($filter)
You cannot call a method on a null-valued expression.
At C:\scripts\ESX-collect-tasks.ps1:20 char:79
+ $collection = (http://VMware.Vim.TaskHistoryCollector$collectionImpl).ReadNextTasks <<<< ($tasknumber)
i'm using the script in your attachment?
can this now be replaced with get-vievent and get-task?
answered my own question..
I'm having problems accessing old events. If i use
Get-VIEvent -Start (get-date).AddDays(-7) | Format-Table CreatedTime, FullFormattedMessage -AutoSize
i still only get same number of events as if i run
Get-VIEvent | Format-Table CreatedTime, FullFormattedMessage -AutoSize
i take it this si because this is the view VC shows us. is there a way to get older events?
Well with the new VITK build the script needed some changes.
Attached one that should work with the current build.
The Get-VIEvent cmdlet returns by default 100 events.
If you need more, use the -MaxSamples parameter.
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
How do I export the output to CSV. I used the Export-CSV cmdlet but it's not populating the file, I assume that script produces an output incompatible to CSV?
This should do the trick.
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
Thank you LucD.
Lucd,
Is it possible to amend the 3rd version of the script to restrict it to only on a per VM basis? I assume by doing so we will not need to increase the number of events variable??
Thanks,
Hugo
Yes, the CreateCollectorForTasks method can be limited to a specific entity via the TaskFilterSpec object.
That would allow us to lower the $tasknumber variable (unless there are a lot of DRS initiated vMotion in the environment).
But that won't really allow us to lower the number in $eventnumber.
The $eventnumber variable is just my stupid way of making sure that I have (on average and not foolproof) enough events to correlate with the task that was found.
Note that I only look for events that are chained via the EventChainId in the TaskInfo object.
This can be done more correctly in a loop where the script tests the number of returned events till it equals 0 (zero). Something like I did in .
That way we are sure we see all the events related to the task.
The $eventnumber variable in this case defines the size of the "window" you scroll over all the events.
If it is lowered, we could have more loops through the "while"-loop.
The script then becomes something like this
$days = 10 $tasknumber = 999 $eventnumber = 100 $vmName = <VM-name> $vm = Get-VM $vmName | Get-View $serviceInstance = get-view ServiceInstance $taskMgr = Get-View TaskManager $eventMgr = Get-View eventManager $report = @() $filter = New-Object VMware.Vim.TaskFilterSpec $filter.Time = New-Object VMware.Vim.TaskFilterSpecByTime $filter.Time.beginTime = (Get-Date).AddDays(-$days) $filter.Time.timeType = "startedTime" $filter.entity = New-Object VMware.Vim.TaskFilterSpecByEntity $filter.entity.entity = $vm.MoRef $collectionImpl = Get-View ($taskMgr.CreateCollectorForTasks($filter)) $dummy = $collectionImpl.RewindCollector $collection = $collectionImpl.ReadNextTasks($tasknumber) $collection | Where-Object {$_.DescriptionId -like "Drm*"} | Sort-Object StartTime | % { $efilter = New-Object VMware.Vim.EventFilterSpec $efilter.eventChainId = $_.EventChainId $ecollectionImpl = Get-View ($eventMgr.CreateCollectorForEvents($efilter)) $ecollection = $ecollectionImpl.ReadNextEvents($eventnumber) while($ecollection -ne $null){ foreach($event in $ecollection){ switch($event.GetType()){ "VMware.Vim.DrsVmMigratedEvent" { $from = $event.SourceHost.Name } "VMware.Vim.VmBeingHotMigratedEvent"{ $to = $event.DestHost.Name } Default {} } } $ecollection = $ecollectionImpl.ReadNextEvents($eventnumber) } $row = "" | Select StartTime, Entity, State, Description, From, To $row.StartTime = $_.StartTime $row.Entity = $_.EntityName $row.State = $_.State $row.Description = $_.DescriptionId $row.From = $from $row.To = $to $report += $row $ecollectionImpl.DestroyCollector() } $report | Export-Csv "C:\DRS-events.csv" -noTypeInformation
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
LucD,
Works like a dream... need quotes around the VM-name to work.. e.g.,
$vmName = "MyServer01"
Many thanks,
Hugo