vmCalgary
Enthusiast
Enthusiast

Power off information from vmware.log

Jump to solution

https://kb.vmware.com/s/article/1019064 taught me quite a bit about what logs in vmware.log for power-down of a machine.I knew about "VMX has left the building" for power down and vmotions. The KB taught me a few others.

See attached code which has been plagiarized from a stun time script. This will be used to confirm VMs have indeed been powered off for greater than 90 days. The last time I did this exercise users claimed they powered on their VMs since the date I stated the VM was powered off. This time, I'm gathering my evidence first. 🤔

1) I'm not strong (yet) in regex. I want to search vmware.log for the following strings.  I'm not sure how to do multiple (greater than 2) or statements.

VMX has left the building

CPU reset

Power

power

vmotion

2) What is this line of code doing: Duration = $fields[2].Split(' ')[6]   

It doesn't give me a duration in days, but something like this (note: the following is a paste from the export-csv output and is a cell). I added the variable Row as that's more useful to me but still want to learn from the plagiarized code.

building:

 

VM Timestamp Duration Row
-- --------- -------- ---
TAM_Health_Amalyzer-5.5.4 11/4/2021 11:26:27 AM 2) {2021-11-04T17:26:27.845Z, vcpu-0, I125: CPU reset: hard...
TAM_Health_Amalyzer-5.5.4 11/4/2021 12:29:08 PM building: {2021-11-04T18:29:08.516Z, vmx, W115: VMX has left the b...

 

 

Tags (2)
0 Kudos
3 Solutions

Accepted Solutions
LucD
Leadership
Leadership

Nearly, but in 1 string

Get-Content -Path $tempFile | where {$_ -match 'VMX has left the building|CPU reset:|power|Power|vmotion|Vmotion' } |


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

View solution in original post

LucD
Leadership
Leadership

Use a try-catch construct around the Copy-DatastoreItem.
If the file does not exist, your script will go to the catch block, where you can log the name of the VM.

The System.STring[] in a CSV indicates that the variable you are exporting contains an array of strings, not a single string.
Export-Csv can't handle that, while the default output formatter to the console can.

An easy fix could be to use the -join operator: $field -join '|'


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

View solution in original post

vmCalgary
Enthusiast
Enthusiast

I'm going to let Excel do some heavy lifting. I'll use out-file and send to txt. Then copy and paste into excel and use the 'convert text to columns' feature.

2021-11-10_15-22-51.jpg

Final code (for now):

 

$vmList = Get-Content C:\users\jmamer\VMware_scripts\SpringCleaning\PoweredOff\all-Nov10.txt # list VMs in txt file 

$report = @()

foreach ($vmName in $vmList) {Get-VM -Name $vmName -PipelineVariable vm |

ForEach-Object -Process {

    $vmxPath = $vm.ExtensionData.Config.Files.VmpathName

    $dsObj = Get-Datastore -Name $vmxPath.Split(']')[0].TrimStart('[')

    New-PSDrive -Location $dsObj -Name DS -PSProvider VimDatastore -Root "\" | Out-Null

    $tempFile = [System.IO.Path]::GetTempFileName()

    Copy-DatastoreItem -Item "DS:\$($vm.Name)\vmware.log" -Destination $tempFile

    Get-Content -Path $tempFile | where {$_ -match 'VMX has left the building|CPU reset:|power|Power|vmotion|Vmotion' } |

    ForEach-Object -Process {

 $fields = $_.Split('|')

    New-Object -TypeName PSObject -Property @{

     VM = $vm.Name

     Timestamp = [DateTime]$fields[0]
          
     Row = $fields

        }

    }

    Remove-Item -Path $tempFile -Confirm:$false

    Remove-PSDrive -Name DS -Confirm:$false

 } |  Select-Object VM,Timestamp,Row }

 

I'll run a function in Excel to see which VMs are missing (no vmware.log).

It could be prettier but I need to get to the analysis part of the problem I'm working on with reclaiming resources. Thanks so much Luc.

View solution in original post

0 Kudos
9 Replies
LucD
Leadership
Leadership

1.
You can combine multiple targets strings with an OR in a RegEx with the vertical bar ('|').
for example, the following "one|two|three", will match the target on 'one' or 'two' or 'three'

2.
Without seeing the code where the content of $fields is created, I can't really explain what the split method is doing.
But it looks as if it splits the string on a dot, and then takes the 7th field.
For example, if the content is "1.2.3.4.5.6.7.8", then it would return "7"

 


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

vmCalgary
Enthusiast
Enthusiast

@LucD,

The script was attached. I guess I should have mentioned that. Turns out my Row variable didn't work well.

$vmList = Get-Content C:\users\jm\VMware_scripts\SpringCleaning\PoweredOff\all-Nov10.txt # list VMs in txt file

$report = @()

foreach ($vmName in $vmList) {Get-VM -Name $vmName -PipelineVariable vm |

ForEach-Object -Process {

$vmxPath = $vm.ExtensionData.Config.Files.VmpathName

$dsObj = Get-Datastore -Name $vmxPath.Split(']')[0].TrimStart('[')

New-PSDrive -Location $dsObj -Name DS -PSProvider VimDatastore -Root "\" | Out-Null

$tempFile = [System.IO.Path]::GetTempFileName()

Copy-DatastoreItem -Item "DS:\$($vm.Name)\vmware.log" -Destination $tempFile

Get-Content -Path $tempFile | where {($_ -match 'VMX has left the building' -or $_ -match 'CPU reset:')} |

ForEach-Object -Process {

$fields = $_.Split('|')

New-Object -TypeName PSObject -Property @{

VM = $vm.Name

Timestamp = [DateTime]$fields[0]

CPU = $fields[1].Trim(' ')

Duration = $fields[2].Split(' ')[6]

Row = $fields

}

}

Remove-Item -Path $tempFile -Confirm:$false

Remove-PSDrive -Name DS -Confirm:$false

} | Select-Object VM,Timestamp,Duration,Row }

 

0 Kudos
LucD
Leadership
Leadership

I'm not sure why you split each line on a vertical bar, in the example lines I don't see any


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

0 Kudos
vmCalgary
Enthusiast
Enthusiast

@LucD wrote:

I'm not sure why you split each line on a vertical bar, in the example lines I don't see any


I wasn't sure what that line was doing in the original code.

VMware.log looks like this, as you well know.

2021-11-04T17:16:28.362Z| vmx| I125: Vix: [956803 mainDispatch.c:4253]: VMAutomation: Ignoring ReportPowerOpFinished because the VMX is shutting down.
2021-11-04T17:16:28.362Z| vmx| I125: Transitioned vmx/execState/val to poweredOff
2021-11-04T17:16:28.362Z| vmx| I125: Vigor_ClientRequestCb: failed to do op=5 on unregistered device 'ConfigParams' (cmd=(null))
2021-11-04T17:16:28.362Z| vmx| I125: VMX idle exit
2021-11-04T17:16:28.378Z| vmx| I125: Vix: [956803 mainDispatch.c:834]: VMAutomation_LateShutdown()
2021-11-04T17:16:28.378Z| vmx| I125: Vix: [956803 mainDispatch.c:783]: VMAutomationCloseListenerSocket. Closing listener socket.
2021-11-04T17:16:28.380Z| vmx| I125: Flushing VMX VMDB connections
2021-11-04T17:16:28.380Z| vmx| I125: VigorTransport_ServerCloseClient: Closing transport 1CB4529850 (err = 0)
2021-11-04T17:16:28.380Z| vmx| I125: VigorTransport_ServerDestroy: server destroyed.
2021-11-04T17:16:28.380Z| vmx| I125: VMX exit (0).
2021-11-04T17:16:28.381Z| vmx| I125: AIOMGR-S : stat o=153 r=308 w=59 i=125 br=4458660 bw=338807
2021-11-04T17:16:28.381Z| vmx| I125: AIOMGR-U : stat o=14 r=12 w=127 i=0 br=96 bw=214512
2021-11-04T17:16:28.381Z| vmx| I125: OBJLIB-LIB: ObjLib cleanup done.
2021-11-04T17:16:28.381Z| vmx| W115: VMX has left the building: 0.

 I'll focus on what I want to get from the log. I want timestamp and the message.

Timestamp

VMX has left the building: 0.

Transitioned vmx/execState/val to poweredOff

VMX exit (0).

Is this how I'd write my regex?

 Get-Content -Path $tempFile | where {$_ -match 'VMX has left the building'|'CPU reset:'|'power|'Power'|'vmotion'|'Vmotion' } |

0 Kudos
LucD
Leadership
Leadership

Nearly, but in 1 string

Get-Content -Path $tempFile | where {$_ -match 'VMX has left the building|CPU reset:|power|Power|vmotion|Vmotion' } |


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

LucD
Leadership
Leadership

I'm not sure how you calculate $duration.

Also, you have to escape special characters in a RegEx.
This seems to work for me (tested with the sample vmware.log extract you posted).

Get-Content -Path .\vmware.log |
where {$_ -match 'VMX has left the building|VMX exit \(0\).|Transitioned vmx/execState/val to poweredOff' } |
ForEach-Object -Process {
    $date,$dummy,$text = $_.Split('|')
    New-Object -TypeName PSObject -Property @{
        Date = [DateTime]$date
        Duration = '?'
    }
}


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

vmCalgary
Enthusiast
Enthusiast

Thank you (as always) Luc. Works much better.

 

Copy-DatastoreItem : 11/10/2021 2:41:01 PM      Copy-DatastoreItem              Cannot find path 'DS:\TAM_Data_collector.sjrb.ad\vmware.log' because it does not
exist.
At C:\users\jmamer\VMware_scripts\SpringCleaning\PoweredOff\VMX-left-the-building.ps1:27 char:5
+     Copy-DatastoreItem -Item "DS:\$($vm.Name)\vmware.log" -Destinatio ...
+     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidArgument: (System.Object[]:Object[]) [Copy-DatastoreItem], VimException
    + FullyQualifiedErrorId : Core_CopyDatastoreItem_TryValidateSourceItem_InvalidSourceItem,VMware.VimAutomation.ViCore.Cmdlets.Commands.CopyD
   atastoreItem

 

I get this is because the script couldn't find a vmware.log file, often the case if the VM has never been powered up, but how do i get a log file of  VM names where vmware.log could not be read?

When I export-csv, the output looks like:

2021-11-10_14-44-34.jpg

When I run on the command line it looks like this:

2021-11-10_14-46-36.jpg

Why?

Joy

PS. I'll use Excel to calculate duration.

0 Kudos
LucD
Leadership
Leadership

Use a try-catch construct around the Copy-DatastoreItem.
If the file does not exist, your script will go to the catch block, where you can log the name of the VM.

The System.STring[] in a CSV indicates that the variable you are exporting contains an array of strings, not a single string.
Export-Csv can't handle that, while the default output formatter to the console can.

An easy fix could be to use the -join operator: $field -join '|'


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

vmCalgary
Enthusiast
Enthusiast

I'm going to let Excel do some heavy lifting. I'll use out-file and send to txt. Then copy and paste into excel and use the 'convert text to columns' feature.

2021-11-10_15-22-51.jpg

Final code (for now):

 

$vmList = Get-Content C:\users\jmamer\VMware_scripts\SpringCleaning\PoweredOff\all-Nov10.txt # list VMs in txt file 

$report = @()

foreach ($vmName in $vmList) {Get-VM -Name $vmName -PipelineVariable vm |

ForEach-Object -Process {

    $vmxPath = $vm.ExtensionData.Config.Files.VmpathName

    $dsObj = Get-Datastore -Name $vmxPath.Split(']')[0].TrimStart('[')

    New-PSDrive -Location $dsObj -Name DS -PSProvider VimDatastore -Root "\" | Out-Null

    $tempFile = [System.IO.Path]::GetTempFileName()

    Copy-DatastoreItem -Item "DS:\$($vm.Name)\vmware.log" -Destination $tempFile

    Get-Content -Path $tempFile | where {$_ -match 'VMX has left the building|CPU reset:|power|Power|vmotion|Vmotion' } |

    ForEach-Object -Process {

 $fields = $_.Split('|')

    New-Object -TypeName PSObject -Property @{

     VM = $vm.Name

     Timestamp = [DateTime]$fields[0]
          
     Row = $fields

        }

    }

    Remove-Item -Path $tempFile -Confirm:$false

    Remove-PSDrive -Name DS -Confirm:$false

 } |  Select-Object VM,Timestamp,Row }

 

I'll run a function in Excel to see which VMs are missing (no vmware.log).

It could be prettier but I need to get to the analysis part of the problem I'm working on with reclaiming resources. Thanks so much Luc.

0 Kudos