vCenter and Host Build Numbers

10.02.2009

This is based on Carter Shanklin’s PowerShell snippets to query VC and ESX build version numbers.

This script loops through the list of vCenter servers, and gets their version and build info, as well as the version and build info for it’s connected hosts.

# Script to connect to a list of vCenter Servers, and get their version numbers, as well as the version numbers of their hosts
# Ben Neise
# 02/10/09
 
# Array of vCenter Servers
$arrVCenterServers = @("server1","server2","server3")
 
# Create empty arrays for the results
$arrTableVCs = @()
$arrTableHosts = @()
 
# Loop through the array of vCenter servers specified above
ForEach ($strVCenterServer in $arrVCenterServers){
	# Connect to the VC
	$objVCenterServer = Connect-VIServer $strVCenterServer
	# Version info about the VC you are connected to
	$viewVCenterServer = Get-View serviceinstance
	# Add custom attributes to each VC objects for version and build
	$objVCenterServer | Add-Member -Name Version -type noteproperty -value ($viewVCenterServer.content.about.Version) -Force
	$objVCenterServer | Add-Member -Name Build -type noteproperty -value ($viewVCenterServer.content.about.Build) -Force
	# Add the VC object to the results array
	$arrTableVCs += $objVCenterServer
	# When connected to loop through the hosts managed by the VC
	ForEach ($objHost in (Get-VMhost | Sort-Object)){
		# Get the view for the current host
		$viewHost = $objHost | Get-View
		# Add custom attributes to the host object for VC server, Host and Version
		$objHost | Add-Member -Name VCServer -type noteproperty -value $objVCenterServer.Name -Force
		$objHost | Add-Member -Name Host -type noteproperty -value $viewHost.Name -Force
		$objHost | Add-Member -Name Version -type noteproperty -value $viewHost.Config.Product.Version -Force
		# Add the host object to the results array
		$arrTableHosts += $objHost
	}
	# Disconnect from the VC server
	Disconnect-VIServer -Confirm:$False
}
# Output the VC results (can be modified to output to a CSV with Export-CSV)
$arrTableVCs | Select-Object Name, Version, Build | Sort-Object Name
 
# Output the Host results (can be modified to output to a CSV with Export-CSV)
$arrTableHosts | Select-Object VCServer, Host, Version, Build | Format-Table
 
# End of script

PowerShell script to add a hash table full of virtual port groups to vSphere hosts

09.17.2009

As part of the migration I’m working on, we needed to add a whole bunch of Virtual Port Groups with associated VLANs to the servers. The following script could do this in a few minutes (although Host Profiles would accomplish much the same thing, we’re not running Enterprise)

# Sets up virtual port groups on all hosts connected to a specific vCenter Server
 
# Name of vCenter Server
$strVCenterServer = "your.vCenter.Server"
 
# VLANs and associated VPGs
$ArrVLANs = @{
	"123" = "Admin";
	"456" = "GPO";
	"789" = "NAG";
}
 
# Connect to the vCenter Server
Connect-VIserver $strVCenterServer
 
# Loop through the VLAN/VPG pairs
ForEach($objVLAN in ($ArrVLANs.Keys | Sort-Object)){
	# Loop through the hosts
	ForEach ($objHost in (Get-VMHost | Sort-Object)){
		# Create the VPG with the VLAN as specified in the array above, on the switch called "VMSwitch" on the current host
		# Remove the "-WhatIf" tag from the end of the following line to "arm" the script
		New-VirtualPortGroup -Name $strNewVPG -VirtualSwitch (Get-Virtualswitch -VMHost $objHost | Where-Object { $_.Name -match "VMswitch" }) -VLanId $strNewVlanTag -WhatIf
		# Write what we've just done to screen
		Write-Host "Adding Virtual Port Group" $ArrVLANs[$objVLAN] "with VLAN Tag" $objVLAN "to" $objHost
	}
}
# Disconnect the session from the host
Disconnect-VIServer -Confirm:$False

Although this isn’t a complicated script, it was the first time I’ve used hash tables (thanks to PowerShell.Com’s excellent page), so I thought I’d share.

Script to add VMX path as a custom attribute

09.15.2009

I love it when I have an idea in my head of a script I need to write, and then I run across one that does exactly what I need!

Hugo Peeter’s has written a script to add VMX location as a Custom Attribute:

Add Vmx Path to VI Client using Powershell | PeetersOnline.nl.

Master-PowerShell With Dr. Tobias Weltner

07.27.2009

Dr Tobias Weltner has released a free comprehensive eBook on PowerShell.

Something to put on your eBook reader.

Export and import customization profiles using PowerShell

07.09.2009

I’m in the middle of preparing for a migration from VI3 to vSphere 4 just now (hence the lack of substantial updating on this site).

As part of this process, I was just about to start writing  a script to export our customisation specifications, when Arnim van Lieshout’s post appeared in my VMware Planet V12N RSS feed.

Export and import customization profiles using Powershell | Arnim van Lieshout.

It failed on a couple of customisations, but by adding…

Write-Host Exporting $CustomizationProfile.name

…after the ForEach loop started, it was easy to see that it was customisations with “/” and “*” characters that were causing the errors.

Cleaning up Template Names

05.28.2009

I wrote this today to remove occurrences of the string “Tmpl” anywhere in the name of the template, and then to re-name the template with “Tmpl” as a prefix. It had a higher purpose than keeping everything nice and neat, but it’s rather specific to our environment so I won’t bother going into the details.

# Get all templates
$objTemplates = Get-Template
 
# Loop through the templates
ForEach ($objTemplate in $objTemplates){
	# Set the $StrInterimTemplateName variable to the template name, replacing the string "Tmpl" with an empty string
	$StrInterimTemplateName = ($objTemplate.Name -replace("Tmpl",""))
	# As the string we've just removed might be anywhere in the name, we need to replace double spaces with single
	$StrInterimTemplateName = ($StrInterimTemplateName -replace("  "," "))
	# And also remove trailing spaces from the start, or the end of the string
	$StrInterimTemplateName = $StrInterimTemplateName.Trim()
	# Display on screen what we're doing (as the "Set-Template" with -WhatIf isn't very clear
	Write-Host Changing `[($objTemplate.Name)`] to `[ Tmpl $StrInterimTemplateName `]
	# Change the Template Name to the $StrInterimTemplateName variable preceeded by "Tmpl", uncomment the #-WhatIf if testing
	Set-Template -Template $objTemplate -Name "Tmpl $StrInterimTemplateName" #-WhatIf
}

Despite being quite specific in it’s current form, this could easily be modified to rename virtual machines (or indeed any other PowerShell object).

While I suspect there’s a more elegant way to do this in fewer steps, it’s not particularly hacky.

VMware PowerCLI 4.0 released

05.26.2009

powerCliLogoI came back from a week’s holiday this morning to find that VMware PowerCLI 4.0 has been released as the successor to VI Toolkit 1.5. The jump from 1.5 to 4.0 is for version number consolidation, rather than being than indicitive of major changes.

They have however fixed one of the bugs that’s been annoying me, which is the inability to change drives to non-persistent, so I’ll need to revisit some of my old scripts from v1.0 and check that they still work.

You can download it from the community page. I’ll follow up with more information when I get a chance to investigate it fully.

Check if servers in a text list exist as VMware VMs

05.13.2009

I got handed a list of around 1000 servers today, and asked if any of them were part of our VI environment.

Rather than work through it by hand, I wrote the following script:

# Check if Servers on Text List exist on VMware
# Assumes that the VM object name matches the server's DNS name
 
# Set this to the text file containing the list of servers, one per line
$strServerList = "C:\path\to\textFile.txt"
 
# Create empty array for servers which are found
$arrFoundServers = @()
 
# Assign all of the VM objects to a variable
$objVMs = Get-VM
 
# Read the list of servers, and assign it to a variable
$strServersOnList = (Get-Content $serverlist)
 
# Loop through each VM
forEach ($objVM in $objVMs){
	# Loop through each server on the list
	forEach ($strServer in $strServersOnList){
		# If the current VM object name matches the current item on the list
		if ($objVM.Name -Like $strServer){
			# Add it to the array of found machines
			$arrFoundServers += $objVM
		}
	}
}
 
# Display the list of found machines
$arrFoundServers

If your VM Object names do not match the DNS names on the list, then this won’t work, but I suppose you could combine this with some logic from the script I wrote to find mismatches.

Thin Provisioning in ESX 3.5

05.06.2009

One of the nice new features of vSphere 4 is thin provisioning of virtual disks. Thin provisioned (TP) disks will be familiar if you’ve ever used VMware Workstation where they are used by default, (you need to select Allocate All Disk Space Now to create thick disks). Essentially, rather than allocate all disk space at creation, disk space is allocated on the fly, meaning that a 50GB virtual disk with only 5GB being used by the guest, would only consume 5GB of space. This can obviously result in real savings, but it does have an impact on machine performance due to the increased disk provisioning overhead as the machine grows.

VirtualGeek had an interesting article on thin-provisioning in vSphere 4, and whether this should be done at the VM level, or at the array level. As well as containing a good description of the different disk types (Thick, Thin & Eagerzeroedthick), there was a brief mention of using TP disks in VI 3.5. This was the first time I’d heard of this, and despite it’s unsupported nature, it deserved some consideration. We’re still using VI 3.5, and disk space is probably our number one capacity constraint; the potential opportunity to reduce our disk-footprint without investing in any new hardware or software was too good to pass up.

I soon discovered that we already used TP disks in a very limited way. One of the options in vCenter’s Clone to Template operation allows the creation of a compact template, and we had been using this to reduce the amount of space used by templates. Templates created in this manner use TP disks, and if you convert that template to a machine, the machine inherits the TP disk. However VMs deployed from the template are created with normal (thick) disks. If you’re curious to see if you’ve got any existing TP machines, Eric Gray wrote a PowerShell script to find existing thin provisioned disks.

After only a little more digging, my dream of being lauded for increasing our free space overnight came to an end. In an article on Virtual Future, Sven Huisman wrote:

Apparently, when you move a VM with a thinprovisioned disk from vCenter server, it converts to a thick-disk. This is because thinprovisioned disks is not integrated with vCenter server yet.

Also, when you deploy from a template with a thinprovisioned disk, the new VM will get a thick-disk.

I imagine this is what they mean by “unsupported”, and this is why the TP functionality in VI 3.5 is largely undocumented.

This changes the conversion process from a one-off time-consuming action to something that would need to be done on an ongoing basis. I think we’ll just have to wait until we get the chance to upgrade to vSphere 4.

Add Drive Persistence State to the VI Client using Powershell

05.05.2009

I’ve further adapted Hugo’s script to add a custom attribute which shows the drive persistence state(s) when the script was run.

The script also adds drive state information for templates as well as VM objects.

# Add drive persistence as a custom attribute for VMs and Templates
 
$VCServerName = "MyVCServer"
$VC = Connect-VIServer $VCServerName
$SI = Get-View ServiceInstance
$CFM = Get-View $SI.Content.CustomFieldsManager
 
# Variables
$CustomFieldName = “HD Persistence”
$ManagedObjectType = “VirtualMachine”
 
# Check if the custom field already exists
$myCustomField = $CFM.Field | Where {$_.Name -eq $CustomFieldName}
If (!$myCustomField){
	# Create Custom Field
	$FieldCopy = $CFM.Field[0]
	$CFM.AddCustomFieldDef($CustomFieldName, $ManagedObjectType, $FieldCopy.FieldDefPrivileges, $FieldCopy.FieldInstancePrivileges)
}
 
# Get the machine objects
$objVMs = (Get-VM) + (Get-Template)
# Loop through each of the machine objects
ForEach ($objVM in $objVMs){
	$strPersistence = ""
	$objHardDisks = $objVM | Get-HardDisk
	# Count the number of hard drives
	$intHardDisks = ($objHardDisks | Measure-Object).count
	# Loop through each of the hard disks
	ForEach ($objHardDisk in $objHardDisks){
		# Replace default persisstence states with initials for brevity
		Switch ($objHardDisk.Persistence) {
			Persistent {
				$strPersistenceInitial = "P"
			}
			IndependentPersistent {
				$strPersistenceInitial = "IP"
			}
			IndependentNonPersistent {
				$strPersistenceInitial = "INP"
			}
		}
		# Concatenate the initial onto the persistence string
		$strPersistence = "$strPersistence" + $strPersistenceInitial
		# If there are more hard drives to add
		If ($intHardDisks -gt 1) {
			# Append a comma and a space (there may be a more elegant way of doing this)
			$strPersistence = "$strPersistence" + ", "
			# Count down the number of hard drives
			$intHardDisks -= 1
		}
	}
	# Add the $strPersistence to custom attribute $CustomFieldName (HD Persistence)
	If ($strPersistence){
		$VMView = $objVM | Get-View
		$VMView.setCustomValue($CustomFieldName,$strPersistence)
	}
}
 
# End of script

« Previous PageNext Page »