Converting between guest OS serial number at VM UUID

A customer recently asked me if it was possible to find a virtual machine BIOS serial number from a virtual machine object or vmx file. While looking into this, I found an old post that provided a very useful hint: https://peppercrew.nl/2011/04/get-virtual-machine-bios-serial-number/. This post contains a PowerShell function to convert a VM UUID to the BIOS serial number. Looking at the code, and reviewing some test VMs, I realized that this is only a string replacement exercise. I’ve seen these serial numbers and UUIDs for years and never made the connection that they were so closely related.

The image below has one example value. The top line is the virtual machine serial number obtained from inside the guest OS (using wmic bios get serialnumber on Windows or dmidecode -s system-serial-number on Linux). The bottom line is the virtual machine UUID (from PowerCLI we can find this with: $vm.ExtensionData.Config.Uuid). The color coding has been added to make the pattern easier to see.

Color coded comparison of VM serial number and UUID

This actually helped explain something I’ve seen before with virtual machines created by storage array-based clones having duplicate UUIDs. The top value (minus the ‘VMware-‘ prefix) is stored in the vmx file as uuid.bios. When a direct clone of the VM file is registered into inventory, the VMs UUID (and by extension, BIOS serial number) would be a duplicate of the original/source VM.

We can see in the following command/output that two VMs have different names / IDs, but have duplicate UUIDs. I’ve confirmed with dmidecode that these two guests also have the same system-serial-number.

Get-VM h207-vm-* | Select-Object Name, ID, @{N='UUID';E={$_.extensiondata.config.uuid}}

Name       Id                        UUID
----       --                        ----
h207-vm-01 VirtualMachine-vm-3147125 42023081-331b-58e1-2730-ca560789e551
h207-vm-02 VirtualMachine-vm-3147127 42023081-331b-58e1-2730-ca560789e551

If we want to change our VM UUID, to ensure all our VMs have unique serial numbers, we can do that with PowerCLI as well. For illustration purposes, I’m going to update the UUID value for the second VM to end with the number 2. However, we could also have PowerShell generate a completely new UUID with [guid]::NewGuid().

$vm = Get-VM h207-vm-02
$spec = New-Object VMware.Vim.VirtualMachineConfigSpec
$spec.uuid = '42023081-331b-58e1-2730-ca560789e552'
$vm.extensiondata.ReconfigVM_Task($spec)

The above code will update our second VM to have a UUID which ends in 552 (the string we provided). In the below code block we’ll get the same two VMs as above and note that our UUIDs have changed.

Get-VM h207-vm-* | Select-Object Name, ID, @{N='UUID';E={$_.extensiondata.config.uuid}}

Name       Id                        UUID
----       --                        ----
h207-vm-01 VirtualMachine-vm-3147125 42023081-331b-58e1-2730-ca560789e551
h207-vm-02 VirtualMachine-vm-3147127 42023081-331b-58e1-2730-ca560789e552

Knowing the BIOS serial number and UUID relationship can be understood with string manipulation, I created a quick function to reverse the original example we found. In this function we can provide a VM system-serial-number and have it select the pieces of the string required to build our UUID.

function Get-VMUuidFromSerial {
  param($vmSerial)
  if ($vmSerial.length -ne 54) { write-warning "The provided serial number $vmSerial does not appear to be the correct length." }

  $myResult = $vmSerial -Replace 'VMware-', '' -Replace ' ', ''
  $myResult.substring(0, 8) + '-' + $myResult.substring(8,4) + '-' + $myResult.SubString(12,4) + '-' + $myResult.Substring(17,4) + '-' + $myResult.Substring(21, $myResult.length - 21)
}

The original code we found expected a parameter of type [VMware.VimAutomation.ViCore.Impl.V1.Inventory.VirtualMachineImpl], but our VM objects were being passed in as [VMware.VimAutomation.ViCore.Impl.V1.VM.UniversalVirtualMachineImpl], so I updated the type definition in the function. To be able to test this using a list of UUIDs from a CSV file, I ended up removing that type definition and checked the length of the string, similar to the above function. I also adjusted the function name to match the format we used above. I’m including it below for reference/safe keeping.

function Get-VMSerialFromUUID {
  param($vmUUID)
  if ($vmUUID.length -ne 36) { write-warning "The provided UUID $vmUUID does not appear to be the correct length." }

  $myResult = 'VMware-'
  $serialnumtmp = $vmUUID.Replace('-','')
  for ($i = 0; $i -lt $serialnumtmp.length; $i += 2) { $myResult += $serialnumtmp.substring($i, 2); if ($myResult.Length -eq 30) {$myResult += '-' } else { $myResult += ' ' } }
  $myResult
}

Hopefully this post will help if you ever need to compare VM UUIDs with BIOS serial numbers and/or resolve duplicate serial number issues.

This entry was posted in Scripting, Virtualization. Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *

*

Notify me of followup comments via e-mail. You can also subscribe without commenting.