# Get the vMotion/svMotion history

The availability of vMotion and svMotion, provided you have a license that allows it, in vSphere are some of its key features.

The DRS and SDRS functionality will use vMotion and svMotion to better use the available resources.

And you as a vSphere administrator can use it to facilitate your work. Just think of how easy patching or datastorecluster maintenance becomes with the help of these two features.
But as an administrator you want to be able to report on what vMotion and svMotion have been doing over a specific time interval in your vSphere environment.

In the past I already provided a vMotion reporting tool in Events – Part 8 – vMotion history, but now it was time to provide a universal (s)vMotion reporting feature.

• User: one or more users for which to return the events
• System: a switch to return all system user events

Update February 10th 2014: it’s always nice to see another implementation based on one of your scripts. The Opvizor solution will soon contain this function, see Dennis Zimmer‘s post called Storage vMotion Activities Report !

## The Script

#### Annotations

Line 1-101: The Get-VIEventPlus function. This function adds some improvements, at least for me, to the current Get-VIEvent cmdlet. It allows you to specify which specific events to return and it allows you to use a ‘recursive’ search for events starting from the ‘Entity’.

Line 52: The function uses the EventHistoryCollector. Access to the found events is through a ‘sliding‘ window. This variable defines the size of that sliding window. From my average use, I came to the conclusion that 100 events is a workable size for this window. But your mileage may vary.

Line 55-85: These lines are the hearth of the function. In here the ‘filter‘ is specified for the events to search for. See the EventFilterSpec objects for the details.

Line 89: The EventFilterSpec can hold only one MoRef. So if multiple entities are passed, they will have be handled one by one. This makes a big difference in execution time when you do not select the value for the Entity parameter correctly. See later.

Line 93-96: This While construction reads all the found events.

Line 103-187: The Get-MotionHistory function. This function uses the Get-VIEventPlus function to retrieve specific events. The returned events are used to report on all the vMotions and svMotions.

Line 140-145: The function has 3 parametersets, each indicating a specific type of interval (Days/Hours/Minutes). The default is 1 day back in time.

Line 151: Since the function supports pipeline input, the history records it creates must be stored in an array until all pipeline objects have been handled.

Line 152-162: The 3 parametersets are handled with a Switch statement, and the Start parameter for the Get-VIEvent cmdlet is calculated accordingly.

Line 163: For the (s)vMotion history the function only needs these 2 types of events.

Line 171: The vMotion and or svMotion actions can be user invoked or system invoked (DRS/SDRS)

Line 173-176: Depending on the type of ‘motion‘, the functions will include a target host or target datastore.

## Sample Usage

The Get-MotionHistory function is quite simple to use as the following example will show.

The content of the produced CSV looks like this.

When you use the Get-MotionHistory take care of what you pass on the Entity parameter !

The following calls will produce the same result.

as this one

But the difference between these two calls of the function is the execution time. The second method was 80 times slower compared to the first method in my test environment, where there are about 100 VMs in that cluster.

The reason is that the Get-VIEventPlus function has to call the EventHistoryCollector for each VM in the 2nd method, while it is only called once in the 1st method !

That is also the main reason I introduced the Recurse parameter on the Get-VIEventPlus function. A feature that is sadly missing on the Get-VIEvent cmdlet 😥

If you want to have a report for a specific set of VMs in a cluster, it is most probably better to call the Get-MotionHistory function for the complete cluster with the Recurse switch set to $true, and filter out the required VMs from the produced result. Something like this for example Enjoy ! ##### 72 Comments #### JacquesM Hello Luc! As usual impressive script. I was looking at getting also if the VM was running at the time of event (for svmotion) I’ve added something like @{N=”PowerState”;E={$_.VM.PowerState}}, as ligne 167… With no luck…

Any chance that the powerstate of VM during an event is available for export into the csv?

thanks a lot!

#### LucD

Hi Jacques,
Thanks.

I’m afraid the powerstate of the VM is not included in the events the script uses.
The VmMigratedEvent for example has a VM property, but that only contains the MoRef to the VM.

You could use events to determine if a VM was powered on at the time of the vMotion, by retrieving the VmPoweredOnEvent and VmPoweredOffEvent.
And then checking what was the last event just before the vMotion.
Luc

#### JacquesM

Thanks Luc!

Thanks for your hard work! I will try to bring up this.

Cheers!
Jacques

#### Eugene

As usual, LucD’s scripts always works. Just copy/paste and no problem. Thanks sharing your knowledge

#### LucD

Well, thank you!

#### MB

Hi Luc,

its really a nice script to pull vmotion information.
How ever the target datastore information was not coming.

#### Tina K

Thank you Luc. That worked!

#### LT

I didn’t look too close in the function but It didn’t work in my environment (VMware 5.5). I came up with this that go through each VM and looks for datastore event. It has a start time and finish time as I wanted to calculate the time it took to vMotion each machine.

$VMotions = @() get-vm | foreach {$VM = $_.name “Querying$VM”

Get-VIEvent -Entity $vm -MaxSamples 10000 | ?{$_.ds -ne $null} | foreach {$VMotions += New-Object PSObject -Property @{VMName=$VM ; StartTime=$_.CreatedTime ; Message=$_.FullFormattedMessage} } } Tweak it as per your need. #### LucD What problems did you encounter with the function? #### Lucas Hi, LucD. Great article and great script. Thank you for that. I’m getting 4 days of vMotions in the output. Do you know how to extend it? Best regards #### Lucas I forgot to write that the vCenter task and events settings is configured to 30 days #### Mohamed Elsaid Hallo LucD.. Thanks for the script. I run it but it gives me blank columns. Although I have done many vMotions. Can you kindly advise? Mohamed #### Ryan Patigayon I got blank output in any parameter, so i modified script from practical admin and working with this output. Name Created UserName Type SourceHost TargetHost Datacenter #### LucD Hi Ryan, Not sure what could be causing this. Would you mind sharing the code you used to call the function? #### Mohamed Elsaid Hallo LucD.. Thanks for the script. I run it but it gives me blank columns. Although I have done many vMotions. Can you kindly advise? Mohamed #### LucD Hi Mohamed, You could first check if you are keeping the Tasks and Events sufficiently long in your vCenter. By default they are kept for 1 year, but that could have been overridden. Can you check which retention period is set in your environment? Luc #### Surendra Mannepalli Dear Luc, I have zero knowledge in scripting ,I am sending the script which i am unable execute, please correct that. please mail me and help me. My emailid: surendra.windows@gmail.com function Get-MotionHistory { param( [CmdletBinding(DefaultParameterSetName=”Days”)] [Parameter(Mandatory=$true,ValueFromPipeline=$true)] [VMware.VimAutomation.ViCore.Impl.V1.Inventory.InventoryItemImpl[]]$prvm-vcsrv.mcgm.gov.in,
[Parameter(ParameterSetName=’Days’)]
[int]$Days = 1, [Parameter(ParameterSetName=’Hours’)] [int]$Hours,
[Parameter(ParameterSetName=’Minutes’)]
[int]$Minutes, [switch]$Recurse = $false, [switch]$Sort = $true ) param( [CmdletBinding(DefaultParameterSetName=”Days”)] [Parameter(Mandatory=$true,ValueFromPipeline=$true)] [VMware.VimAutomation.ViCore.Impl.V1.Inventory.InventoryItemImpl[]]$prvm-vcsrv.mcgm.gov.in,
[Parameter(ParameterSetName=’Days’)]
[int]$Days, [Parameter(ParameterSetName=’Hours’)] [int]$Hours,
[Parameter(ParameterSetName=’Minutes’)]
[int]$Minutes, [switch]$Recurse = $false, [switch]$Sort = $true ) begin{$history = @()
switch($psCmdlet.ParameterSetName){ ‘Days’ {$start = (Get-Date).AddDays(- $Days) } ‘Hours’ {$start = (Get-Date).AddHours(- $Hours) } ‘Minutes’ {$start = (Get-Date).AddMinutes(- $Minutes) } }$eventTypes = “DrsVmMigratedEvent”,”VmMigratedEvent”
}

process{
$history += Get-VIEventPlus -Entity$entity -Start $start -EventType$eventTypes -Recurse:$Recurse | Select CreatedTime, @{N=”Type”;E={ if($_.SourceDatastore.Name -eq $_.Ds.Name){“vMotion”}else{“svMotion”}}}, @{N=”UserName”;E={if($_.UserName){$_.UserName}else{“System”}}}, @{N=”VM”;E={$_.VM.Name}},
@{N=”SrcVMHost”;E={$_.SourceHost.Name.Split(‘.’)[0]}}, @{N=”TgtVMHost”;E={if($_.Host.Name -ne $_.SourceHost.Name){$_.Host.Name.Split(‘.’)[0]}}},
@{N=”SrcDatastore”;E={$_.SourceDatastore.Name}}, @{N=”TgtDatastore”;E={if($_.Ds.Name -ne $_.SourceDatastore.Name){$_.Ds.Name}}}
}

end{
if($Sort){$history | Sort-Object -Property CreatedTime
}
else{
$history } } } At C:\powershell\Get-MotionHistory.ps1:6 char:77 + [VMware.VimAutomation.ViCore.Impl.V1.Inventory.InventoryItemImpl[]]$prvm-vcs …
+ ~
Missing ‘)’ in function parameter list.
At C:\powershell\Get-MotionHistory.ps1:2 char:28
+ function Get-MotionHistory {
+ ~
Missing closing ‘}’ in statement block.
At C:\powershell\Get-MotionHistory.ps1:15 char:3
+ )
+ ~
Unexpected token ‘)’ in expression or statement.
At C:\powershell\Get-MotionHistory.ps1:20 char:77
+ [VMware.VimAutomation.ViCore.Impl.V1.Inventory.InventoryItemImpl[]]$prvm-vcs … + ~~~~ Unexpected token ‘-vcsrv’ in expression or statement. At C:\powershell\Get-MotionHistory.ps1:20 char:83 + … l[]]$prvm-vcsrv.mcgm.gov.in,
+ ~~~~~~~~~~~~
Unexpected token ‘.mcgm.gov.in’ in expression or statement.
At C:\powershell\Get-MotionHistory.ps1:20 char:83

#### Nick

How complex would it be to add the end time of the task?

#### chris

Works great, but the reported time is 2 hours behind.

My vCenter and ESXi has NTP configured and shows the correct time.

Any guess?

#### LucD

Hi Chris,
I suspect this due to the fact the vSphere internally stores all events in UTC. When you retrieve them, they come out with a UTC timestamp.
You can easily change it to your local TZ with
 $_.CreatedTime.ToLocalTime()  Hope this helps. Luc #### Oliver Hi, I’m trying to use this against vCenter 6 (tried PowerCLI 5.1/6) and it just gives me no results like it’s not even trying. No error or anything. Any ideas? #### LucD Sorry to hear that Oliver. Would you mind sharing the script with which you call the function ? And are there any error messages ? #### Yvan Comte Hi Luc Quick question. I am trying to use your script to collect (s)vmotion info from 2 different vcenters (I connect at the beginning of the script, then I pass a system.array populated with a list of VM object I read from a csv list of VMs foreach ($MyVM in $OSSvm_List) {$OSSVM += ($MyVM.Host) } get-MotionHistory -Entity (get-vm$OSSVM) -days $Nbr_days the problem I have is that I get VM in the$history that are not at all in the import list nor in the system.array variable I pass to your get-MotionHistory fct?

Any idea?
Help very much appreciated and thanks the great contribution to the community

#### LucD

Hi,
Do these extra VMs you are getting back, have a name that is similar to the ones you did pass to the function ?
For example, you include the VM name VM123, but you also get back VM1234.

#### Yvan Comte

Hi Luc
No, the returned VM are not in the system array I am passing. When I breakpoint and look at $entity passed (e.g. line 52) I see the correct VM list. Then it process and the output includes VMs that are not required. As said I connect to 2 vcenters, but “should” not be an issue. Actually what I do to produce the report is pipe the output of get-MotionHistory liek this: Get-MotionHistory -entity (get-VM$OSSVM) -Days $Nbr_days | convertTo-html -head$a -body $b -Title$myTitle | set-content -Path Microsoft.PowerShell.Core\FileSystem::\\spt.swi.srse.net\davwwwroot\it\se\is\vb\reports\OSS_vmotion_report_test.htm

/yvan

#### Stephane

Thanks a lot lot Luc for the script. Very useful.

I’d like to get the date including seconds whereas so far I get 08/07/2015 16:30.

How can this be done ?

#### Manuel Risco-Herrera

I was struggling with Get-VIEevent cmdlet up to a point that I decided to load Onyx. Suddenly, I remembered LucD (and the chances of having a handy module that will save my day)

I was not wrong, you saved it.

Thanks heaps dude,

Manuel

#### Carl Sattler

Thanks for this. Due to the model of my array and the fw on it, I suffer from SVmotion corruption and now that I have disabled VAAI hdwr acceleration, I wanted to learn where I could identify VMs potentially afflicted. This was a silver bullet but I can’t get it to work. I get prompted for:

InputObject: df233PowerCLI C:\users\adm-sattler\desktop\Useful PS1 commands> .\SVmotions_Get_CSV_rev1.ps1

cmdlet Export-Csv at command pipeline position 1
Supply values for the following parameters:
InputObject: 4

and when I open the resulting CSV file, I get two entries in cells: (A1=Length, A2=1):
| A | B
1| Length
2| 1

Different inputs result different values in A2 but nothing like I would hope for in terms of column headings and useful timedate stamps indicating when migrations and relocations occurred.

Thanks much

Carl

#### LucD

Strange, could you forward me the .ps1 file in which you have the script.
I suspect there might have been some copy/paste errors.

Use the mail link on the page top-right

#### Carl Sattler

Hi and thanks for replying. I leveraged an onsite admin who is more familiar with PS than I am (not difficult) and he had me load it as a function . .\script and then run the commands and it output as suggested. Thanks again.

The usecase is that due to a bug in an older fw rev of the array (which with VAAI hdwr acceleration enabled results in corruption), I wanted to look for potentially affected machines that had been relocated (svmotion). This report covers that. It would also be good if I could identify those VMs that have an uptime (since rebooting seems to exhibit corruption symptoms) so if the uptime was > time since svmotion, we could then focus on those VMs and treat with more care.

I found this script and would really like to use it but I cam getting an error on line 91 where the $eventCollector is setup, its aborting. Any chance on an updated version for 5.5?. #### Nathan Very cool script. Came in very handy. I typically avoid downloading other people’s scripts in my environment, but it really seemed like there wasn’t a better way to accomplish what you are doing here. I was able to expand this very easily to accomplish the task I was looking to do – which was essentially to determine what host a server was located on for a certain date. #### LucD Glad it was useful for you #### Anil Hello, Great it works like a charm, But here in my environment all the hosts connected to vCenter with IP addresses, so when i generate the report in the srcVMhost it is showing only 192 instead of full IP address even in dest also. Any thing need to chenge from the script to get the complete IP address. Thanks, Anil #### Scott Thanks LucD, This has been very helpful in the past few days as we have MS Auditors wanting to know how many times our SQL Servers have vMotioned in the past 90 days. However, I have just noticed that the script doesn’t include DRS relocation event triggered by the Power On virtual machine task. But they have only asked for vMotions so that is ok 🙂 #### admin Thanks. I’ll check if I can include those vMotions as well in the script. #### Yoav Slama Thanks for your script but it doesn’t work for me, no matter which parameters i used i always get a blank CSV file, please help me. Thanks. #### LucD Do you have some more details on what you did ? How did you call the function ? From the prompt, from another script ? Any error messages ? #### Yoav Slama Before i executed the script i added according to your examples another command in the end of the script, for example: Get-MotionHistory -Entity (Get-VM VM*) -Days 1 | Export-Csv C:\motion-report1.csv -NoTypeINformation -UseCulture After that i executed your script (./ScriptName). I also tried all of your examples, and i tried to change their parameters but nothing helped, the output is blank every single time with no errors. PowerCLI version: 5.0.1.4431 and 5.5.0.5836 (tried to execute the script on each one of them) vCenter version: 4.1 and 5.1 (tried to execute the script on each one of them) Thanks for your help! #### Yoav Slama I tried to execute the script by adding according to your examples another command in the end of the script, for example: Get-MotionHistory -Entity (Get-VM VM*) -Days 1 | Export-Csv C:\motion-report1.csv -NoTypeINformation -UseCulture I tried all of your examples, and i also tried to change their parameters but nothing helped, the output is blank every single time with no errors (i executed the script by writing: ./NameOfTheScript.ps1 in the PowerCLI command line). PowerCLI version: 5.0.1.4431 and 5.5.0.5836 (i tried to execute the script on each one of them) vCenter version: 4.1 and 5.1 (i tried to execute the script on each one of them) Thanks for your help! #### Rocky From where and how to run these script??????? What are the pre-requisites?? How to understand, what needs to be modified?? Thanks for quick reply #### ranjit when i run the “Get-MotionHistory -Entity (Get-VM VM*) -Days 1 | Export-Csv C:\motion-report1.csv -NoTypeINformation -UseCulture” it creates blank file. #### Zach I keep getting an Input dialog box pop up running the script with : Get-Cluster -Name Cluster1 | Get-MotionHistory -Hours 4 -Recurse:$true
Export-Csv C:\motion-report1.csv -NoTypeINformation -UseCulture

Hi Zach,
Did you pipe the results of the function call to the Export-Csv cmdlet ?
The vertical bar at the end of the 1st line ?
 Get-Cluster -Name Cluster1 | Get-MotionHistory -Hours 4 -Recurse:$true | Export-Csv C:\motion-report1.csv -NoTypeINformation -UseCulture  If that doesn’t solve the issue, what is the exact message you are seeing ? #### keith Great Script! I am able to get everything functioning except the sourcedatastore.name. Any ideas on why it would not populate? #### akamac Hi, Luc. How can I find out possible values for event type? #### internetrush Method invocation failed because [System.Object[]] doesn’t contain a method named ‘CreateCollectorForEvents’. At line:57 char:69 +$eventCollector = Get-View ($eventMgr.CreateCollectorForEvents <<<< ($eventFilter))
+ CategoryInfo : InvalidOperation: (CreateCollectorForEvents:String) [], RuntimeException
+ FullyQualifiedErrorId : MethodNotFound

You cannot call a method on a null-valued expression.
At line:58 char:53
+ $eventsBuffer =$eventCollector.ReadNextEvents <<<< ($eventnumber) + CategoryInfo : InvalidOperation: (ReadNextEvents:String) [], RuntimeException + FullyQualifiedErrorId : InvokeMethodOnNull You cannot call a method on a null-valued expression. At line:63 char:39 +$eventCollector.DestroyCollector <<<< ()
+ CategoryInfo : InvalidOperation: (DestroyCollector:String) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull

Code does not work when passing a single vm using the most recent powercli

#### Matt Andes

Luc,

I was playing around with your Get-VIEventPlus function while working on something else and it appears that the CreatedTime property on the events that the function spits out are in UTC.

Funny thing is that the start and finish date I gave it were in local time and it pulled all of the correct events but the output it gave me had the UTC time which made it weird and was playing havoc with my script because according to the output the last event was after my finish time parameter.

Is this intended? As a side note I was able to get around this by adding this before you spit out the events on line 65:

Foreach ($event in$events) {
$event.CreatedTime =$event.CreatedTime.ToLocalTime()
}
$events #### admin That is correct, the Tasks and Events when retrieved with a HistoryCollector are indeed returning UTC timestamps. I’ll add a switch to the function that allows you to select LocalTime. #### Prabhurj Hello LucD, Thanks for the Nice script, Get-MotionHistory does not works on powercli version 5.1 release 1 and 2? any alternate version that you suggest? Thanks, Prabhu #### Methone Hello, Is it possible to bring svmotion and vMotion History in vCheck I really appreciate that Best regards #### michael works perfectly now, thanks! #### michael thanks Luc, this script came in very handy for checking an specific issue we had. I received the below error but it still provided the results we needed when running: Get-Cluster -Name “*cluster*” | Get-MotionHistory -Hours 4 -Recurse:$true

Exception setting “endTime”: “Cannot convert null to type “System.DateTime”.”
At C:\vmware\vmotion.ps1:52 char:7
+ $eventFilter.time.endTime =$Finish
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], SetValueInvocationException
+ FullyQualifiedErrorId : ExceptionWhenSetting

@Michael, it looks as if that was a “feature” in the Get-VIEventPlus function 😉 Nice catch.
I changed the function slightly, the Finish parameter now has a default value.
Can you check if that solves your problem ?

#### Robert van den Nieuwendijk

Cool stuff as always. I specially like the Get-VIEventPlus -Recurse parameter.

#### LucD

Thanks Robert.

This site uses Akismet to reduce spam. Learn how your comment data is processed.