Virtu-Al.Net

Virtually everything is POSHable

Who created that VM ?

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

, ,

39 thoughts on “Who created that VM ?

  • Luis says:

    This data is coming from vCenter right? We just recently migrated from one vCenter server to another and I’m noticing that most of the VM’s don’t have a creation event type. They have a discovered event and that’s from when the new vCenter server first started to manage the VM’s. I’m going to end up retrieving the OS Install date from WMI and use that date as an alternative for Windows based VM’s that don’t have a creation type of event. That should give me a fairly close time to when the VM was first created.

  • [...] informacji na temat kto stworzył daną maszynę, lecz do tego posłużyłem się skryptem z wpisu VIRTU-AL.NET who created that [...]

  • Itay Mesholam says:

    Hi,

    i just got this error while runing the script :

    parameter cannot be found that accepts argument ‘class=goog_qs-tidbit goog_qs-tidbit-0>Core

    can i get your help please?

  • mkbell says:

    Help! I need to pull out all this list of virtual machines, to include their OS type, names, Ipaddress, cpu, memory. Just like all the information we see on a virtual machine summary.

  • Gareth Wilson says:

    If you deploy machines from templates then it just seems to return unknown, uknown for the creation user and date ?

  • [...] then found an excellent script compiled by Alan Renouf (@alanrenouf) at http://www.virtu-al.net/2010/02/23/who-created-that-vm. The script has a dependently on vSphere PowerCLI (obviously!) and ActiveRoles Management Shell [...]

  • Hemant Patel says:

    Hi,

    Really good script and it running perfectly. But when we run the script it cache the previous username who created VM and add this name in all VM’s rather than adding correct name.

    Is there any way to come out from this?

    Hemant

  • Michael says:

    Very nice one.. Is it possible to restrict the script so only a particular VM is being queried ? For instance, we are trying to find out when one single VM is being created but we need to avoid that the annotation of 100s of VMs is being modified … Would

    $VMs = Get-VM -name vm1

    do the trick ?

  • Sybux says:

    Hi,
    1st, thanx for your script it help me a lot.
    I’ve run it on my vCenter and it returns a little number of result. I’ve combined yours with another one I’ve found on Internet and now it looks in all event.

    I’ve added this lines at the begining :
    # Go very far in past to get all events and enough
    $start = (Get-Date).AddDays(-1999)
    $eventNr = 999999

    And I’ve changed the $Event blabla to use this parameters.
    $Event = $VM | Get-VIEvent -Start $start -MaxSamples $eventNr | Where-Object { $_.Gettype().Name -eq “VmBeingDeployedEvent” -or $_.Gettype().Name -eq “VmCreatedEvent” -or $_.Gettype().Name -eq “VmRegisteredEvent” -or $_.Gettype().Name -eq “VmClonedEvent”}

  • Warren says:

    Could this script be altered to only show VM’s in a particular cluster? Very interested to know who did what in our server cluster, but not interested in VDI cluster for exmample. Thanks

    • Alan says:

      Sure, just change the line that currently reads:

      $VMs = Get-VM | Sort Name

      to the following:

      $VMs = Get-Cluster MyCluster | Get-VM | Sort Name

1 2

Leave a Reply