I was asked whilst on a customer site to work out who had created a VM, this is a common question in most environments where admin rights are the normal and creating a VM is as easy as creating a new word document.

After trawling through the logs for a couple of minutes I found the creator and told the customer, easy enough I guess but how could we make this easier ?

The answer to that question will be no surprise to most readers of this blog….. PowerCLI !

With a quick script and resolving the user account in AD, I was able to add a custom field to each VM letting me know who created the VM and when it was created, all displayed in the annotations of each VM as seen below:

image

Connect-VIServer MYVISERVER
# Uncomment the next line to test this script and tell you what it would do !
# $WhatIfPreference = $true
if (-not (Get-PSSnapin VMware.VimAutomation.Core -ErrorAction SilentlyContinue)) {
	Add-PSSnapin VMware.VimAutomation.Core
}
if (-not (Get-PSSnapin Quest.ActiveRoles.ADManagement -ErrorAction SilentlyContinue)) {
	Add-PSSnapin Quest.ActiveRoles.ADManagement
}

$VMs = Get-VM | Sort Name
$VM = $VMs | Select -First 1
If (-not $vm.CustomFields.ContainsKey("CreatedBy")) {
	Write-Host "Creating CreatedBy Custom field for all VM's"
	New-CustomAttribute -TargetType VirtualMachine -Name CreatedBy | Out-Null
}
If (-not $vm.CustomFields.ContainsKey("CreatedOn")) {
	Write-Host "Creating CreatedOn Custom field for all VM's"
	New-CustomAttribute -TargetType VirtualMachine -Name CreatedOn | Out-Null
}
Foreach ($VM in $VMs){
	If ($vm.CustomFields["CreatedBy"] -eq $null -or $vm.CustomFields["CreatedBy"] -eq ""){
		Write-Host "Finding creator for $vm"
		$Event = $VM | Get-VIEvent -Types Info | Where { $_.Gettype().Name -eq "VmBeingDeployedEvent" -or $_.Gettype().Name -eq "VmCreatedEvent" -or $_.Gettype().Name -eq "VmRegisteredEvent" -or $_.Gettype().Name -eq "VmClonedEvent"}
		If (($Event | Measure-Object).Count -eq 0){
			$User = "Unknown"
			$Created = "Unknown"
		} Else {
			If ($Event.Username -eq "" -or $Event.Username -eq $null) {
				$User = "Unknown"
			} Else {
				$User = (Get-QADUser -Identity $Event.Username).DisplayName
				if ($User -eq $null -or $User -eq ""){
					$User = $Event.Username
				}
				$Created = $Event.CreatedTime
			}
		}
		Write "Adding info to $($VM.Name)"
		Write-Host -ForegroundColor Yellow "CreatedBy $User"
		$VM | Set-CustomField -Name "CreatedBy" -Value $User | Out-Null
		Write-Host -ForegroundColor Yellow "CreatedOn $Created"
		$VM | Set-CustomField -Name "CreatedOn" -Value $Created | Out-Null
	}
}

The script is fairly straight forward, a few caveats are worth mentioning though:

  • This script uses the Quest AD cmdlets to resolve the username in AD, if you don’t have these installed then you can either install them or use the Microsoft AD cmdelts or I have a small function which will do the same thing, I previously used this here.
  • This may take a long time if the VM was created a long time ago as unfortunately the Get-VIEvent cmdlet does not have a way to start from the beginning of the events so I need to retrieve all events for that VM and then filter on them.
  • If the VM’s were removed from the virtual center and then re-added it will have the name of the person who re-imported or added the VM, not the original creator.

Once we have the information added to the VM’s we can of course do some cool reporting, like who created the VM’s:

Get-VM | Select Name -ExpandProperty CustomFields | Where {$_.key -eq "CreatedBy"} | Out-GridView

image

Or even who created the most VMs:

Get-VM | Select Name -ExpandProperty CustomFields | Where {$_.key -eq "CreatedBy"} | Group-Object | Select Count, Name | Sort Count -Descending |Out-GridView 

image