0

List of VMX Files

Don’t ask me why but I wanted a list of .VMX files for all of the virtual machines registered in vCenter. With a little experimentation it was easy to come up with a oneliner.

[ps]Get-VM | Get-View | % { $_.Config.Files.VmPathName }[/ps]

However, that’s not the quickest way. The output takes ages to display because each VM is passed along the pipeline one at a time resulting in multiple Get-View queries. The following is faster:

[ps]Get-View -ViewType VirtualMachine | % { $_.Config.Files.VmPathName }[/ps]

Although it is a bigger query, the single Get-View call makes the whole thing so much faster. I learned that the other week at a fantastic VMware event. Cheers Alan.

Now, one question I have. Most of the VMX files returned by this take the following form:

[text][datastore_name] VM-Name/VM-Name.vmx[/text]

However, there were a few that came out as:

[text][] /vmfs/volumes/datastore-id-string/VM-Name/VM-Name.vmx[/text]

Does anyone know why that’s happening? They’re all from the same datastore, perhaps there’s an issue with that…

0

Display vSCSIStats Data With Microsoft Chart Controls

I had to run vSCSIStats for the first time in a while the other day. Normally, trying to display the data that it outputs in a graphical form involves some cutting and pasting and a wrestling match with Excel. I recalled this time that someone had tried to automate the process in the past and a quick google search sent me to Gabe’s site and an article that he wrote back in February. The Excel macro (written by Paul Dunn) that was the subject of the article looked like just the job but I couldn’t get it to work for some reason. I’m not very good with vbscript and so I started to wonder if it might be possible to do it with PowerShell…

Another quick google suggested Microsoft Chart Controls for .NET 3.5 as a potentially useful tool. Originally I had planned to simply write a script that used Excel as I have done in the past. However, that approach might not have been the quickest and easiest thing to do.

Although there are quite a few people using the Chart Controls, most of the content out there focuses on coding / scripting languages other than PowerShell. The best PowerShell example that I found was in this article by Richard Macdonald. It’s a great introduction and well worth a read. In fact, as you’ll below, it formed the foundation of my script.

So, first things first, some pre-requisites:

That’s it. Except of course that we need some data.

The environment that I’m working in uses ESX still rather than ESXi. As such, vSCSIStats is already present and easy to get to using an SSH connection the the server hosting the VM that you’re interested in. Once on the server I had to obtain the worldGroupID of the VM that I wanted to monitor. This was done simply by issuing the following command:

[shell]/usr/lib/vmware/bin/vscsiStats -l[/shell]

Which returned the following output:

[shell]Virtual Machine worldGroupID: 6146, Virtual Machine Display Name: XXXXXXX {
Virtual SCSI Disk handleID: 8193
Virtual SCSI Disk handleID: 8194
Virtual SCSI Disk handleID: 8195
Virtual SCSI Disk handleID: 8196
Virtual SCSI Disk handleID: 8197
Virtual SCSI Disk handleID: 8198
}[/shell]

As you can see, the worldGroupID for the VM is 6146. The disks listed are the Hard Disks presented to the VM in the order in which they are listed in the VM’s settings. A bit detective work is required to work out which disk ID maps to which drive letter in the VM. Fortunately, it was easy enough to discover that the disk that I was most interested in has an ID of 8194.

Now, to run vSCSIStats and collect some data I had to issue the following command:

[shell]/usr/lib/vmware/bin/vscsiStats -s -w 6146[/shell]

And this is the output that I received:

[shell]vscsiStats: Starting Vscsi stats collection for worldGroup 6146, handleID 8193
Success.
vscsiStats: Starting Vscsi stats collection for worldGroup 6146, handleID 8194
Success.
vscsiStats: Starting Vscsi stats collection for worldGroup 6146, handleID 8195
Success.
vscsiStats: Starting Vscsi stats collection for worldGroup 6146, handleID 8196
Success.
vscsiStats: Starting Vscsi stats collection for worldGroup 6146, handleID 8197
Success.
vscsiStats: Starting Vscsi stats collection for worldGroup 6146, handleID 8198
Success.[/shell]

I left it running for about 30 minutes and then used the following command to export the histogram data to a CSV file:

[shell]/usr/lib/vmware/bin/vscsiStats -p all -w 6146 -c > /root/vscsiStats-export.csv[/shell]

I also used this command to stop the stats collection from continuing:

[shell]/usr/lib/vmware/bin/vscsiStats -x[/shell]

Finally, I used Veeam’s FastSCP tool to copy the CSV file back to my desktop machine.

Looking inside the CSV file using a text editor, I saw this:

[text]Histogram: IO lengths of commands,virtual machine worldGroupID,6146,virtual disk handleID,8193
min,512
max,65536
mean,4456
count,13257
Frequency,Histogram Bucket Limit
6165,512
75,1024
567,2048
575,4095
2428,4096
72,8191
2270,8192
222,16383
636,16384
110,32768
16,49152
10,65535
111,65536
0,81920
0,131072
0,262144
0,524288
0,524288[/text]

This is the data that I will use to create a single histogram. The CSV file will generally contain many more datasets. One for each metric multiplied the the number of disks present. This is why it could be so tedious copying and pasting the data into Excel.

Nothing needs to be changed in the CSV file, the script that I wrote works with it as it is. All I did was place it in the same folder and the script and then executed the script from within PowerShell. There was nothing exciting to see when it ran in the console but within a few seconds a histogram was displayed using the data from above. Each dataset from the CSV file was rendered as a histogram in turn. Simply by closing the graph window, the script moved onto the next dataset and rendered it until I got to the ones that I wanted. Remember the disk handleID from earlier? It was 8194. This is the IO latency histogram for that disk:

Displaying the data and interpreting the data are two different things so I won’t go into it much now. You can see though that disk IO latency varies between 0.5ms and 100ms and mostly sits at 15 – 30ms. That’s what I wanted to know.

So, now for the script. As I mentioned earlier, I based it around the work that Richard Macdonald had already done so you’ll see some sections of code that are very similar looking to snippets from his article. The rest I cobbled together so the whole thing is a bit clunky. I’ll give it a polish sometime soon.

[ps]###########################################################
# vSCSIStats-Histograms.ps1
#
# Version:    0.1
# Author:    Michael Poore (www.vspecialist.co.uk)
#
# Uses Microsoft Chart Controls to draw charts from CSV data
# outputed by vSCSIStats
###########################################################

$thisXData = ""
$thisYData = ""
$rawData = Import-Csv "vscsistats-export.csv" -Header "Field","Value","worldGroupID","diskHandleIDHeader","diskHandleID"

$dataCollection = @()

foreach( $row in $rawData )
{
$row.Field -match "([a-zA-Z0-9-()]+)" | Out-Null
switch( $matches[0] )
{
"Histogram" {
if( test-path variable:thisHistogram )
{
$thisHistogram | Add-Member -Name XData -Value $thisXData -Membertype NoteProperty
$thisHistogram | Add-Member -Name YData -Value $thisYData -Membertype NoteProperty
$dataCollection += $thisHistogram
}
Remove-Variable -Name thisXData
Remove-Variable -Name thisYData
$thisHistogram = New-Object PSObject
$thisHistogram | Add-Member -Name Title -Value $row.Field -Membertype NoteProperty
$thisHistogram | Add-Member -Name worldGroupID -Value $row.worldGroupID -Membertype NoteProperty
$thisHistogram | Add-Member -Name diskHandleID -Value $row.diskHandleID -Membertype NoteProperty
$thisXData = @()
$thisYData = @()
}
"min" {
$thisHistogram | Add-Member -Name Min -Value $row.Value -Membertype NoteProperty
}
"max" {
$thisHistogram | Add-Member -Name Max -Value $row.Value -Membertype NoteProperty
}
"mean" {
$thisHistogram | Add-Member -Name Mean -Value $row.Value -Membertype NoteProperty
}
"count" {
$thisHistogram | Add-Member -Name Count -Value $row.Value -Membertype NoteProperty
}
"Frequency" {
#Do nothing
}
default {
#Assumed to be data
$thisXData += $row.Value
$thisYData += $row.Field
}
}
}

#Load Charting Assemblies
[void][Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
[void][Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms.DataVisualization")

foreach( $chart in $dataCollection )
{

$thisTitle = $chart.Title + " (worldGroupID " + $chart.worldGroupID + ", diskHandleID " + $chart.diskHandleID + ")"

#Create Chart Object
$thisChart = New-object System.Windows.Forms.DataVisualization.Charting.Chart
$thisChart.Width = 900
$thisChart.Height = 600
$thisChart.Left = 40
$thisChart.Top = 30

#Create ChartArea
$ChartArea = New-Object System.Windows.Forms.DataVisualization.Charting.ChartArea
$ChartArea.AxisX.Interval = 1
$ChartArea.AxisX.TextOrientation = "Rotated90"
$thisChart.ChartAreas.Add($ChartArea)

[void]$thisChart.Series.Add("Data")
$thisChart.Series["Data"].Points.DataBindXY($chart.XData, $chart.YData)

#Add Title
[void]$thisChart.Titles.Add($thisTitle)

#Change Chart Colour
$thisChart.BackColor = [System.Drawing.Color]::Transparent

#Make Bars Into 3d Cylinders
$thisChart.Series["Data"]["DrawingStyle"] = "Cylinder"

# add a save button
$SaveButton = New-Object Windows.Forms.Button
$SaveButton.Text = "Save"
$SaveButton.Top = 10
$SaveButton.Left = 900
$SaveButton.Anchor = [System.Windows.Forms.AnchorStyles]::Bottom -bor [System.Windows.Forms.AnchorStyles]::Right
$SaveButton.add_click({$thisChart.SaveImage($Env:USERPROFILE + "Desktop" + [System.Text.RegularExpressions.Regex]::Replace($thisTitle,"[^1-9a-zA-Z_]","_") +".png", "PNG")})

# display the chart on a form
$thisChart.Anchor = [System.Windows.Forms.AnchorStyles]::Bottom -bor [System.Windows.Forms.AnchorStyles]::Right -bor [System.Windows.Forms.AnchorStyles]::Top -bor [System.Windows.Forms.AnchorStyles]::Left
$thisForm = New-Object Windows.Forms.Form
$thisForm.Text = $thisTitle
$thisForm.Width = 1000
$thisForm.Height = 700
$thisForm.controls.add($SaveButton)
$thisForm.controls.add($thisChart)
$thisForm.Add_Shown({$thisForm.Activate()})
$thisForm.ShowDialog()

}[/ps]

vSCSIStats-Histograms

Subsequently to writing this script and getting the charts and information that I wanted, I discovered that David Owen (@vMackem) has been experimenting with Chart Controls also. We compared notes over a few beers after IP Expo yesterday. His article is a good read and efficiently produces a nice pie chart from his script. I’m looking forward to hearing about his other discoveries with Chart Controls, PowerShell and PowerCLI.

0

PowerCLI: New cmdlets for Update Manager

VMware have this morning / last night released some PowerCLI cmdlets for VMware Update Manager (VUM). A short description can be found of them below:

Cmdlet Name Cmdlet Description
Attach-Baseline Attaches baselines to the specified Template, VirtualMachine, VMHost, Cluster, Datacenter, Folder, and VApp objects.

Attaching a baseline to a container object such as a folder or datacenter transitively attaches the baseline to all objects in the container.

Detach-Baseline Detaches baselines from the specified inventory objects.
Download-Patch Downloads new patches into the Update Manager patch repository from the enabled patch download sources.
Get-Baseline Retrieves the baselines specified by the provided cmdlet

parameters.

Get-Compliance Retrieve baseline compliance data for the specified object of type Template, VirtualMachine, VMHost, Cluster, Datacenter, Folder, and VApp.
Get-Patch Retrieves all available patches or those specified by the provided cmdlet parameters.
Get-PatchBaseline Retrieves all  patch baselines or those specified by the provided cmdlet parameters.
New-PatchBaseline Creates a new patch baseline. Patch baselines can be applied to either hosts or virtual machines. Depending on the patch criteria you select, patch baselines can be either dynamic or static (fixed).
Remediate-Inventory Remediates an inventory object against the specified baselines.
Remove-Baseline Deletes the specified baselines from their servers. Before the

removal, the baselines are detached from all entities they have been attached to.

Scan-Inventory Scans inventory objects for baselines attached to them.
Set-PatchBaseline Modifies the properties of a patch baseline. You can specify explicitly the patches you want to include in the baseline through the IncludePatch parameter.
Stage-Patch Initializes staging of patches. Staging allows you to download

patches from the Update Manager server to the ESX/ESXi hosts, without applying the patches immediately.

The cmdlets can be downloaded from VMware’s website as a PowerShell Snapin and require PowerCLI 4.0 U1.

I look forward to seeing a few scripts pop out in the next few days that make use of these.

0

Basics: Open PowerCLI using different credentials

Everytime I use a different PC or laptop I always forget to do this after installing PowerCLI. I happily open PowerCLI up and try to connect to a vCenter server and get prompted for my login information. This is how I feel:

Every time in that session that “Connect-VIServer” is used I’ll get it because my normal domain account doesn’t have any privileges in vCenter. The point of this post isn’t to teach anyone to suck eggs but maybe it’ll help me remember in future to make one tiny change after installing PowerCLI.

Right click on the PowerCLI shortcut and open the shortcut’s properties.

Click the “Advanced” button.

Tick the box “Run with different credentials”. OK everything.

The next time the the shortcut is used the option to specify different credentials is shown:

Entering a different account here saves having to do it each time “Connect-VIServer” is used. There are other things that can be done of course. Maybe I’ll save those for another day.