WhoCreatedTheVM

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

46 thoughts on “Who created that VM ?”

  1. You have to use a script to find out who built a VM?? Why was VMWare too lazy to develop an option of putting that in the logs. This is something that should be in the Event Logs. This should not require using a Powershell script. What type of crap is this?? Unprofessional garbage…

  2. This script rocks my only issue seems to be its only pulling data that is extremely recent, meaning today. so if a machine is created today it finds its and populates correctly but if the machine was created yesterday or later it doesn’t find it.

    am i doing something wrong or not editing a field i don’t see?

  3. Is there a newer version of this that uses tags instead of custom attributes? It looks like it may be simple to change it over if you are good with programming – which I’m not…

  4. Custom Fields are not the recommended way to do things these days.
    Here is a version of the script using Tags.
    It’s a cleanup of another script I have in production and this script is not tested in any way.
    The script stores only who created the VM not when. I didn’t need it at the time of writing and it’s trivial to add. 🙂
    I only needed the login name without the domain component so no check against AD.
    If you need the full name of the user you can easily do it with the Active Directory Module.
    Example: $user=(Get-ADUser ).Name

    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
    }

    try
    {
    $category=Get-TagCategory -Name “Created by” -ea stop
    }
    catch
    {
    Write-Host “Creating Tag Category: Created by”
    New-TagCategory -Name “Created by” -Description “Tags with those who created the objects” -Cardinality “Single” -EntityType “VirtualMachine”
    }

    $VMs = Get-VM | Sort Name
    $VM = $VMs | Select -First 1

    Foreach ($VM in $VMs){
    $Event = $VM | Get-VIEvent -Types Info | Where { $_.Gettype().Name -eq “VmBeingDeployedEvent” -or $_.Gettype().Name -eq “VmCreatedEvent” -or $_.Gettype().Name -eq “VmClonedEvent” -or $_.Gettype().Name -eq “VmRegisteredEvent”}
    if(($Event | Measure-Object).Count -eq 0)
    {
    $user=”Unknown”
    $desc=”No information about user found”
    }
    else
    {
    if($Event.Username -eq “” -or $Event.Username -eq $null)
    {
    $user=”Unknown”
    $desc=”No information about user found”
    }
    else
    {
    $user=($Event.Username -split “\\”)[1]
    $desc=”Who created the object”
    }
    }

    $tag=$null
    try
    {
    $tag=Get-Tag -Name $user -Category “Created by” -ea stop
    }
    catch
    {
    Write-Host “Creating Tag $($user)”
    $tag=New-Tag -Name $user -Category “Created by” -Description $desc
    }

    $tags=$vm | get-TagAssignment

    $hastag=$false
    if($tags -ne $null)
    {
    foreach($t in $tags.Tag)
    {
    if($t.Category.Name -eq “Created by”)
    {
    $hastag=$true
    }
    }

    }

    if(-not $hastag)
    {
    try
    {
    Write-Host “Assigning $($tag.Name)”
    $tmp=New-TagAssignMent -Tag $tag -Entity $vm
    }
    catch
    {
    Write-Error “Failed to assign Tag $($tag.Name) to VM $($vm.Name)”
    }
    }
    }

  5. Alan,

    Does this work for vSphere 5.5 with a W2003 Domain?

    When I run it in my 5.5 environment I get “Unknown” for both user and creation date.

    Any ideas?

    Regards

    Steve

  6. 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.

  7. 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?

  8. 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.

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

  10. 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

  11. 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 ?

  12. 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”}

  13. 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

    1. Sure, just change the line that currently reads:

      $VMs = Get-VM | Sort Name

      to the following:

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

  14. I’m fairly new to PowerCLI and have a question about the $WhatIfPreference line. I did a find and only found it in line 3. Shouldn’t I see it being checked somewhere farther down in the script? Otherwise, how could it prevent something being written or created?

    Thanks,
    Doug

  15. Many thanks for the script ! 🙂
    Works perfectly in my test/dev environment, with c. 20 VMs. In my production environment, against either of 2 vCentres, (c. 190 VMs each) it gives the following error…

    Encountered end of line while processing a string token.
    At line:1 char:3
    + . ” <<<< d:\scripts\Who_Created_VMs.ps1

    Any ideas, please ?

  16. vCenter events do expire. Based on looking at Alan’s script, the “Unknown”s are there either because some VMs are too old, so vCenter no longer has events for those VMs of type “VmBeingDeployedEvent”, “VmCreatedEvent”, “VmRegisteredEvent”, “VmClonedEvent”, or else because those events for some reason have a blank or null Username field. You can add in some write statements to see which is the cause. If you have to associate *some” user with each VM, but that user doesn’t necessarily need to be the one that deployed/created/registered/cloned it (i.e. someone that powered it on is OK), then you could consider removing the where clause that filters for those event types, and add a sort by createdTime, and just pull of the first user you find. An example without any AD lookup is at http://www.vmdev.info/?p=311.

  17. Why would I see a lot of Unknowns? Is every single event for a vm stored forever? Or is it possible that they are only kept for 3-6 months and then deleted? Also, would it return unknown if the user is no longer in AD? Say they left the company or something?

  18. It’s okay I figured it out, I just re commented the “WhatIfPreference line”

    Thanks for your work :=)

  19. Hi,

    The script seems to work (because there are no errors except sometimes “domain either not exist”) but the custom fields are not displayed in the annotations box… Have I to create the 2 fields manually?

    Thanks,

    Syl

  20. Hi Al,

    Thanks for the info on the resource change info will try soon.

    My timeout issue occured for several of the first servers it ran against then I stopped the run after 5 or 6 servers. The VC is 2.4 U4. I know some stuff may be an issue before we get to vSphere but am hoping to get some stuff.

    Thanks!

  21. @Tinsymth

    As for your timeout issue I havent seen this before, does it complete any of the VMs or do you get this on the first one ? How old is your VC ?

  22. @Tinsmyth

    Unfortunaatly I dont thing the details are stored in the events so you may find this hard to fine, it looks like it just logs it as a resource change, you can however get a list of resource changes by using something similar to the following:

    Get-VM TestVM | Get-VIEvent | Where { $_.Gettype().Name -eq “VmResourceReallocatedEvent”} | Select CreatedTime, UserName, FullFormattedMessage

    Hope this helps.

  23. Hi Al,

    Well I ran the script and uncommented the line so I could see what it would do and I am getting the following timeout: Get-VIEvent : The operation has timed out
    At C:\Program Files\VMware\Infrastructure\vSphere PowerCLI\WhoCreatedThatVM.ps1
    :23 char:29
    + $Event = $VM | Get-VIEvent <<<< -Types Info | Where { $_.Gettype().N
    ame -eq "VmBeingDeployedEvent" -or $_.Gettype().Name -eq "VmCreatedEvent" -or $

    etc., I did install the Quest AD cmdlets but not sure if its related or not. Thanks!

  24. Hi Al,

    I haven’t run the script yet but it certainly looks like one I can use. I am just getting started with the PowerShell/PowerCLI environment, but I can see learning it will be a good move. I need to be able to get in to my virtual machine settings and find out who has been changing the memory limits in the resource tab. They have caused us big performance problems and I sure would like to know who and why its being done.

    Thanks to you and LucD for helping us newbies out with these scripts!

  25. Troy,

    That is strange, its working fine here, i just tried adding another New VM and running the script and it updated fine.. Hmmm

  26. Hey Al,

    I ran this script against my test environment. Worked great the first time through. However if I add new VM’s and run it again, it erases any previous Annotations and doesn’t add the new. The PCLI interface says it has added it, but the vSphere Client doesn’t show anything. More information can be provided if needed.

  27. Brian,

    How are you copying the code, are you using the source viewer icon when you hover over the script ?

    Also, do you have the Quest AD cmdlets installed ?

  28. Hey love your scripts… I copied this and I get an error “Unexpected Token ‘if’ in expression or statement. At line:9 char:6

    I am not a scripter so not sure what this means however it looks ok….
    ideas?

Leave a Reply