Aug/093
Set VMware Snapshot Location with Powershell
Snapshots are m*th3rfcukers. If you’re not careful, they will mass-murder your vms. Yet they allow you to time-travel! You want to use them, but how to prevent a massacre? Here’s how: relocate the delta files.
When you create a snapshot, the current state of the vm is preserved by leaving the disk files alone. All changes since the moment of creating the snapshot are written to delta files. The delta files are stored in the vm’s working directory. The working directory is – by default – the location where the vmx and other config files reside. If that datastore runs out of free space – especially if it also contains disk files – you’re in a bit of a kerfuffle. Vms not booting or being frozen as if they stared into Medusa’s reptoid eyes.
So you can do two things: reserve overhead in your datastores and stay afraid some overactive snapshot might destroy your environment, or set the working directory of your vms to some big-ass datastore you don’t use for anything else and let the snapshots enjoy themselves. If they fill up the datastore, they only kill all vms with snapshots, not the rest.
But how, you ask? You can edit the vmx files of you vms manually - which requires your vms to be powered down – and add the line: workingDir = “/vmfs/volumes/<insanely long guid you need to somehow find>/”
Or, you run my script and change the working location on the fly:
# Description:
# Set's the Working Location for a VM. This location will hold the vswap and snapshot delta files.
# Usage:
# First, connect to a virtual server server (Connect-VIServer)
#
# Set snapshot location for one vm (folder must already exist on datastore):
# Set-VMSnapshotLocation -vm VM001 -Location "[BigAssDatastore] Snapshots"
#
# For all vms at once (no folder specified will put all in the root of the datastore):
# Get-VM | ForEach-Object {Set-VMSnapshotLocation -vm $_ -Location "[BigAssDatastore]"}
#
# Reset the location to the original location (with the vmx file):
# Set-VMSnapshotLocation -vm VM001 -Reset
Function Set-VMSnapshotLocation
{
param($vm, [string]$Location, [switch]$Reset=$False)
#Region Input Validation
# Check vm parameter
If (!$vm)
{
Throw "No VM specified."
}
# Check Location parameter.
# Can be empty when using Reset, can be "[datastore]" or can be "[datastore] folder" (folder must exist).
If (!$Reset -and $Location -notmatch "\[\S+\](\s\w+)?")
{
Throw "Invalid location specified. Syntax: [Datastore] Folder"
}
# Specifying Reset will set Location to empty, which causes the original location to be used (same location as vmx file).
If ($Reset)
{
$Location = ""
}
# Make sure to get a vm object to work with.
# This allows both using a vm name when targeting one vm (Set-VMSnapshotLocation -vm VM001 -Reset);
# AND piping a collection of vm's (Get-VM | ForEach (Set-VMSnapshotLocation -vm $_ -Location "[BigAssDatastore] Snapshots" ).
If ($vm.GetType().Name -eq "String")
{
$oVM = Get-VM $vm
}
ElseIf ($vm.GetType().Name -eq "VirtualMachineImpl")
{
$oVM = $vm
}
Else
{
Throw "Parameter vm is of an invalid type."
}
#EndRegion InputValidation
#Region Main
# Get advanced properties of vm
$vmView = $oVM | Get-View
# Create object containing new properties
$vmConfigSpec = New-Object VMware.Vim.VirtualMachineConfigSpec
$vmConfigSpec.Files = New-Object VMware.Vim.VirtualMachineFileInfo
$vmConfigSpec.Files.SnapshotDirectory = $Location
# Reconfigure VM using new properties
$vmView.ReconfigVM($vmConfigSpec)
#EndRegion Main
}
You can download it here: Set-VMSnapshotLocation (rename to .ps1)
I tried hard as I could, but I could not get my vm to die. Even running the script, creating a snapshot, running the script to move the working location again and deleting the snapshot did not prove a problem. However, I urge you to be careful with it. I’m not responsable for anything you do with it.
Tiny glitch: the VI Client shows the wrong datastore location when a vm has a snapshot in a modified workingdir.
Enjoy.
Jun/090
Create a vSwitch Port Overview with Powershell
WARNING: VMware vmotion does not check wether there are sufficient ports available on the virtual switch on the destination host. Migrating a vm to a host with insufficient ports will cause the vmotion to complete without warnings, yet the virtual NIC will be disconnected! This issue is descripbed in this KB article.
The solution to this problem is to create vSwitches with sufficient ports, obviously. Do you want to know how many ports are currently being used on every vSwitch in your environment? vSphere PowerCLI to the rescue! Try the following script:
$VC = Connect-VIServer "MyVCServer" $myCol = @() ForEach ($VMHost in (Get-VMHost | Sort Name)) { ForEach ($VM in ($VMHost | Get-VM)) { ForEach ($NIC in (Get-NetworkAdapter -VM $VM)) { $myObj = "" | Select VMHost, VM, NIC, PortGroup, vSwitch $myObj.VMHost = $VMHost.Name $myObj.VM = $VM.Name $myObj.NIC = $NIC.Name $myObj.PortGroup = Get-VirtualPortGroup -VM $VM -Name $NIC.NetworkName $myObj.vSwitch = $myObj.PortGroup.VirtualSwitchName $myCol += $myObj } } } $myCol | Group-Object VMHost, vSwitch -NoElement | Sort Name | Select Name, Count Disconnect-VIServer -Confirm:$false
May/094
Oneliner: Service Console IP with PowerCLI
Getting the Service Console IP addresses of your ESX servers with vSphere PowerCLI (formerly known as the VI Toolkit for Powershell):
Get-VMHost | Select Name, @{N="ConsoleIP";E={(Get-VMHostNetwork).ConsoleNic | ForEach{$_.IP}}}
Mar/093
Translate Vml to LUN Path with Powershell
While checking the vmkernel logs on our VMware ESX Servers today, I ran into some errors referencing luns using a vml string. It looks something like this: vml.827149017315617. I would like to know what lun this error is referencing, but I prefer the LUN Path notation, e.g.: vmhba1:2:137. So I wrote this Powershell VI Toolkit function that can translate the vml into the lun path:
# Function: Translate a VML (e.g.: vml.9364839746917650) to a Lun Path (e.g.: vmhba1:2:137) function Translate-VmlToLunPath { param( [string]$VMHostName, [string]$Vml ) Return (Get-VMHost $VMhostName | Get-ScsiLun | Where {$_.ConsoleDeviceName -match $Vml}).CanonicalName }
Feed it a host name and a vml string and it will return the lun path. Here’s an example script that uses this function when looking for LUNs with SCSI Reservation Errors:
# Example use in a script: Get LUNs with SCSI Reservation Conflicts $VIServerName = "myVIServer" $NumLines = 1000 $VC = Connect-VIServer $VIServerName ForEach ($VMHost in Get-VMHost) { ForEach ($Log in ($VMHost | Get-Log -Key vmkernel -NumLines $NumLines)) { $MatchedEntries = $Log.Entries | Where {$_ -match "reservation" -and $_ -match "vml.\d*"} ForEach ($VmlId in $matches.values) { $myObj = "" | Select VMHost, ErrorLun $myObj.VMHost = $VMHost.Name $myObj.ErrorLun = Translate-VmlToLunPath -VMHostName $VMHost.Name -Vml $VmlId Return $myObj } } } Disconnect-VIServer -Confirm:$False
Enjoy!
Hugo
Feb/093
Checking VMware NTP configuration with Powershell
Thanks to the VMware VI Toolkit 1.5, checking the NTP settings on all your VMware ESX Servers is as easy as a oneliner:
Get-VMHost | Sort Name | Select Name, @{N=”NTP”;E={Get-VMHostNtpServer $_}}
Jan/092
VI Toolkit 1.5 Getting Started and Undocumented Functions
0. Installing
Installing or upgrading the VI Toolkit 1.5 is as easy as Next, Next, Finish. And using the new VI Toolkit shortcut on your desktop allows quick and easy access to the Toolkit. But what about running these cmdlets from your scripts or integrating it with other snapins? Read on!
1. Setting up your profile
The new desktop shortcut does two things for you: it starts powershell with the VI Toolkit snapin loaded and it runs a script which modified the look of the Powershell window ánd adds some cool extra functions. If you want to have the same functionality in your normal Powershell window and your scripts, you have to copy some stuff to your Powershell profile. First, set up your profile:
a. Start a normal Powershell window.
b. Run the following command: Test-Path $profile
c. Did it return True? Then you already have a profile file. Did it return False, do step d.
d. Create a profile file by running: New-Item $profile -ItemType File
2. Adding the snap-in
a. Open your profile by running: Invoke-Item $profile
b. Add the following line to the profile file to load the snap-in: Add-PSSnapIn VMware.VimAutomation.Core -ErrorAction SilentlyContinue
3. Adding undocumented functions
a. Open the file C:\Program Files\VMware\Infrastructure\VIToolkitForWindows\Scripts\Initialize-VIToolkitEnvironment.ps1
b. Copy the following Function Blocks to your profile file: Get-VICommand, New-DatastoreDrive, New-VIInventoryDrive, Get-VIToolkitDocumentation, Get-VIToolkitCommunity
4. Undocumented Functions?
Ok, you can read about them in the Administrator’s Guide (http://www.vmware.com/support/developer/windowstoolkit/wintk10/doc/viwin_admin.pdf), but you might overlook these functions because they are not cmdlets, so Get-Command won’t show them (nor will Auto-Complete work for them).
Here’s a short description of each of them:
- Get-VICommand: Displays all VI Toolkit cmdlets (equal to: Get-Command -PSSnapIn VMware.VimAutomation.Core);
- New-DatastoreDrive: Allows you to browse a datastore like a drive (Example Usage: New-DatastoreDrive -Name <DriveName> -Datastore (Get-Datastore <DatastoreName>); Then jump to the drive: cd <DriveName>: );
- New-VIInventoryDrive: Allows you to browse your Virtual Infrastructure like a drive (Example Usage: New-VIInventoryDrive -Name <DriveName> -Location (Get-Inventory <Folder-/Cluster-/ResourcePool-/HostName>); Then jump to drive: cd <DriveName>: );
- Get-VIToolkitDocumentation: Opens the VI Toolkit Command Reference Help File;
- Get-VIToolkitCommunity: Opens the VI Toolkit Community website.
More examples and scripts here soon!
Hugo
Jan/0916
Check VMware Configuration with Powershell
I have promised you I would post this script, so here it is!
This Powershell script generates an overview of any items that are not available to every ESX server in a VMware cluster. These items might prevent your vm’s being vmotioned by DRS or restarted by HA. Pretty serious business, I’d say!
The items involved are:
1. datastores
2. LUNs (important when using Raw Device Mappings)
3. port groups
The output is a nicely formatted HTML page showing not only which items are misconfigured, but also where the are available and where they are absent.
And here’s the script:
Compare-Clusters (Rename to .ps1)
Enjoy!
Hugo
Jan/090
Compare Cluster Datastores with Powershell
I showed you before how to compare the datastores for two ESX Servers using the VI Toolkit. But ideally, one would like to compare all ESX servers in a cluster to ensure VMotion and HA compatibility.
So I started scripting and it turns out to be pretty simple: only 4 lines of code in Powershell! It does the comparison for all your clusters and returns clean little tables with datastores you should investigate.
SCRIPT CODE:
ForEach ($Cluster in (Get-Cluster | Sort Name))
{
$VMHosts = Get-Cluster $Cluster.Name | Get-VMHost
$Datastores = $VMHosts | Get-Datastore
$VMHosts | ForEach {Compare-Object $Datastores ($_ | Get-Datastore)} | ForEach {$_.InputObject} | Sort Name | Select @{N=$Cluster.Name;E={$_.Name}} -Unique | Format-Table
}
SAMPLE OUTPUT:
TEST CLUSTER 1
——————
DATASTORE1
LOCAL01
LOCAL02
LOCAL03TEST CLUSTER 2
——————
DATASTORE2
DATASTORE3
LOCAL06
LOCAL07
LOCAL08
LOCAL09
Coming very soon: a full-blown script that compares datastores, LUNs and portgroups across your clusters ánd identifies exactly where the differences are! Stay tuned…
Jan/0922
Another way to gather VMware disk info with Powershell
I’ve created another way to gather and display VMware Virtual Disk information with the Powershell VI Toolkit.
The attached script generates a csv-file with all Virtual Machines’ Disks, in which Datastore they are stored, the LUN IDs of the extents that make up this Datastore (in HEX) and the Vendor of the SAN those LUNs are on (just in case you have multiple). Simpy a great way to determine which LUNs are used by which virtual server(s) in a complex environment.
By the way: the script is filled with comments to allow you to learn how it works.
create-vmdiskoverview (Rename to .ps1)
Enjoy!
Hugo
Jan/098
Compare ESX configurations with Powershell
One of the challenges in managing a large VMware Infrastructure is keeping all ESX Servers within a cluster equal. This is essential for having vmotion capabilities and therefore essential for a solid HA configuration. I have showed you earlier how to add the LUN Count for each ESX Server to your VI Client. This allows you to spot differences quickly. But finding exactly which datastores are missing on which ESX Server can be a bigger challenge.
Here are some small functions that can help you determine where the major differences are.
Comparing datastores:
function Compare-VMHostDatastores
{
param([string]$host1,[string]$host2)
$a = Get-VMHost $host1 | Get-Datastore | %{$_.Name}
$b = Get-VMHost $host2 | Get-Datastore | %{$_.Name}
Compare-Object $a $b
}
Compare-VMHostDatastores esxServer1 esxServer2
InputObject SideIndicator
———– ————-
esxServer1_Local <=
esxServer2_Local =>
DATASTORE_TEST1 =>
And comparing Port Groups:
function Compare-VMHostPortgroups
{
param([string]$host1,[string]$host2)
$a = Get-VirtualPortGroup (Get-VMHost $host1) | %{$_.Name}
$b = Get-VirtualPortGroup (Get-VMHost $host2) | %{$_.Name}
Compare-Object $a $b
}
Compare-VMHostPortgroups esxServer1 esxServer2
InputObject SideIndicator
———– ————-
PortGroup_TEST <=
Internal <=
Maybe you prefer to go the other way around and check to which ESX servers a specific datastore is attached?
function Get-DatastoreHosts
{
param([string]$datastore)
Get-VMHost -Datastore (Get-Datastore $datastore) | Sort Name | %{$_.Name}
}
PS D:Scripts> Get-DatastoreHosts DATASTORE_TEST1
esxServer2
esxServer3
Thank Microsoft for Powershell and the Compare-Object cmdlet!
Hugo

