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.

SnapReminder sends e-mails to owners of snapshots

06.26.2009

I love this script from Alan Renouf:-

[F]ind the offending snapshot, find the person who created it, get their email address from AD and send them an email reminding them of their mortal sin.

Our IndependentNonPersistent drives here prevent us from using snapshots, but I’m working on a “utilisation checking” script, that should help us cull some neglected machines and I might integrate some of Al’s AD interrogation into that.

Virtu-Al » PowerCLI: SnapReminder.

VMware Developer CodeCentral

06.24.2009

VMware have launched a new community site for code examples, and there’s a section on VMware vSphere PowerCLI (formerly VI Toolkit).

They seem to be picking the best scripts from the regular contributors to the forums, so it’s a good place to have a look for examples. They’re rated by users, and tend to be slightly better documented than the ones posted in the forums (which tend to be appended and amended as the thread progresses).

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.

Virtual Machine Blue Screen Detector

05.15.2009

Carter Shanklin has used use of Microsoft Office Document Imaging Library (MODI) to improve Eric Sloof’s script to detect Blue Screens of Death (BSoDs); it now captures the errors and converts them to text.

From Eric’s blog:

[F]irst it captures a screenshot of a virtual machine. Secondly it uses the Toolkit Extensions to copy it to the local drive. When the PNG image is saved on the local drive, it’s converted to TIFF. The TIFF image will be used to extract the text using OCR.

It’s the kind of thing that naieve users expect computers to be able to do, but which actually turn out to be rather difficult tasks. It’s an incredible use of the various technologies involved – PowerCLI, the Toolkit Extensions, MODI and PrimalForms.

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.

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

Add Disk Size Information to the VI Client using Powershell

04.29.2009

This is based on Hugo Peeters’ script to Add Snapshot Information to the VI Client using Powershell.

Our users occasionally need larger machines created for packaging big applications.  After increasing the size, we used to append the VM Object name (e.g, “PACKVM01 – 10GB”), but this caused a mismatch between the virtual machine object name in VIC and the DNS host name. Also, it looked untidy!

We needed a new way for VIC users to be able to tell which were the larger machines, so I modified Hugo’s script to add disk size as a custom attribute.

# Add disk size as a custom attribute
 
$VCServerName = “MYVCSERVER”
$VC = Connect-VIServer $VCServerName
$SI = Get-View ServiceInstance
$CFM = Get-View $SI.Content.CustomFieldsManager
 
# Variables
$CustomFieldName = “HD Size (GB)$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)
}
 
$objVMs = Get-VM
ForEach ($objVM in $objVMs){
	$objTotalDiskSize = 0
	# Sum the total size of all disks attached to the VM
	ForEach	($objHardDisk in ($objVM | Get-HardDisk)){
			$objTotalDiskSize += ($objHardDisk.CapacityKB/1024/1024)
			}
	If ($objTotalDiskSize){
		# Round the size to one decimal place
		$objHDSize = "{0:N1}" -f $objTotalDiskSize
		$VMView = $objVM | Get-View
		$VMView.setCustomValue($CustomFieldName,$objHDSize)
	}
}

Creating new Virtual Port Groups in ESX with PowerShell

04.28.2009

We frequently need to create new virtual port groups on our ESX hosts with VLAN tags which correspond to pre-assigned DHCP scopes. I wrote this PowerShell script to create the new VPG across all hosts.

$strNewVPG = "newVirtualPortGroup"
$strNewVlanTag = "123"
 
$ObjAllHosts = Get-VMHost | Sort-Object -Property Name
 
ForEach($objHost in $ObjAllHosts){
    $strVSwitch = Get-Virtualswitch -VMHost (Get-VMHost $objHost) | where-object { $_.Name -match "VMswitch" }
    Write-Host "Adding Virtual Port Group" $strNewVPG "with VLAN Tag" $strNewVlanTag "to" $objHost
    New-VirtualPortGroup -Name $strNewVPG -VirtualSwitch $strVSwitch -VLanId $strNewVlanTag
}

This assumes that your virtual port group is on a switch called “VMSwitch”. You could easily modify this to accept parameters from the command-line, rather than being specified in the script.

When it comes to re-naming existing virtual port groups across hosts there doesn’t seem to be an inbuilt cmdlet, instead I wrote a script to delete the old VPG, and create a new one with the same VLAN tag:-

$strOldVPG = "OldVPGName"
$strNewVPG = "NewVPGName"
$ObjAllHosts = (get-vmhost | Where-Object { $_.Name -notlike "e3acspacesxbu.lim.emea.dell.com" } | Sort-Object -Property Name)
ForEach($objHost in $ObjAllHosts){
    Write-Host " "
    Write-Host "Changing Virtual Port Group Settings on" $objHost
    $strVSwitch = Get-Virtualswitch -VMHost (Get-VMHost $objHost) | where-object { $_.Name -match "VMswitch" }
    $objOldVPG = Get-VirtualPortGroup (Get-VMHost $objHost) | where-object { $_.Name -match $strOldVPG }
    Write-Host "Removing Virtual Port Group" $objOldVPG
    Remove-VirtualPortGroup -VirtualPortGroup $objOldVPG -confirm:$false -whatif
    Write-Host "Adding Virtual Port Group" $strNewVPG "with VLAN Tag" $objOldVPG.VLanID
    New-VirtualPortGroup -Name $strNewVPG -VirtualSwitch $strVSwitch -VLanId $objOldVPG.VLanID -confirm:$false -WhatIf
}

Run it once to check it’s doing what you want, then remove the -WhatIf tags to run it for real.

« Previous PageNext Page »