VMware Cloud Community
dustin_walker
Contributor
Contributor

Is there a command to get the name of the VM I am running on?

Hello,

I am woking on an aoutomated build system, where I run concurrent builds on multiple VMs in parallel.
In my script, I would like to get the name of the VM where the script runs.

example:
I have 2 VMs: "build_vm1" and "build_vm2"
The same build system runs on both VMs in parallel.

Now I need a command like "Get-VM -this ", which returns " either "build_vm1" or "build_vm2" depending on which machine the command is executed on.

Thanks for your help

0 Kudos
10 Replies
StephenMoll
Expert
Expert

I think the easiest solution would be arrange for the VMs to have hostnames that match the name of underlying VM, so they can simply use $env.COMPUTERNAME inside their PowerShell scripts.

 

Or

 

You could create a PowerCLI script to run through all VMs and push their VM names to each VM using a scriptblock running through the VMTools Guest Operations API to write the VM name to the internal environment variable space. Henceforth the VM will internally have a record of its own VM name in vSphere.

0 Kudos
LucD
Leadership
Leadership

Yes, you can use the guestinfo concept.

Query the content of guestinfo variables with the vmtools command.
You can even set your own variables (outside the VM) with Set-AdvancedSetting and then query the value inside the Guest OS with the vmtoolsd command.

A short example

 

$vmName = 'MyVM'

$code = @"
"C:\Program Files\VMware\VMware Tools\vmtoolsd.exe" --cmd "info-get guestinfo.vmhost"
"@

$vm = Get-VM -Name $vmName

try{
  New-AdvancedSetting -Entity $vm -Name 'guestinfo.vmhost' -Value $vm.VMHost.Name -Confirm:$false -ErrorAction Stop | Out-Null
}
catch{
    Get-AdvancedSetting -Entity $vm -Name guestinfo.vmhost -ErrorAction Stop |
    Set-AdvancedSetting -Value $vm.VMHost.Name -Confirm:$false | Out-Null
  }

Invoke-VMScript -VM $vm -ScriptText $code -ScriptType Bat |
Select -ExpandProperty ScriptOutput

 




Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

0 Kudos
StephenMoll
Expert
Expert

Luc, the OP doesn't have the value for $vmName to start with.

That is what I believe the OP wants the VM to determine for itself.

 

LucD
Leadership
Leadership

It depends on where in his build process the VM is in fact.

If the VMware Tools are not yet installed or running, the GuestOperations nor the guestinfo option will work.
Also, if the build involves a rename of the hostname in the Guest OS, even the 'hostname' command could still be off.

The OP should provide more information on the build process he is using.
Is this a clone from a Template?
Is this a new VM from an ISO?

...


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

0 Kudos
dustin_walker
Contributor
Contributor

The VMs in question are new vms from an Iso (manually deployed)
These VMs each  dynamically create a new temporary VM, where the software is built.
The script were the build process is defined runs on the manually deployed VM.

Here I want to figure out the name of the vm were my script runs, so that I can derive a new unique name for my temp vm.

For my usecase I found out, that both the "hostname" and the "$env:COMPUTERNAME" powershell comand return me the hostname of my vm, which in my case is the same as the name of my vm in vphere.
(This is only the case, because the person, that has setup the VMs has configured it that way)

This means my problem is solved.
However, I think, that there should be a powercli command like "Get-VM -this"

Or does the vsphere server not have this information?

Thank you.

0 Kudos
LucD
Leadership
Leadership

Not really in a direct way.

Another way of getting the VM's DisplayName, which relies on the prereqs that the VMware Tools are running and that you have PowerCLI installed and have network connectivity in the Guest OS, is to make a connection to the VCSA (Connect-VIServer)), and then do

$sessionMgr = Get-View SessionManager
$vm = Get-VM | where{$_.Guest.IPAddress -Contains $sessionMgr.CurrentSession.IpAddress}
$vm.Name

But being able to make a link between the Guest OS hostname and the VM's DisplayName is not something that should be readily available (without meeting some prereqs).
That would be a serious security flaw.


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

0 Kudos
dustin_walker
Contributor
Contributor

i think it is possible without vmwaretools, if we crawl all mac addresses

$mac = (get-netadapter | Select-Object -ExpandProperty MacAddress)[0]
Get-VM | Get-NetworkAdapter | Where {$_.MacAddress -eq $mac.Replace('-',':')} | Select-object Parent

 

0 Kudos
LucD
Leadership
Leadership

Yes, that would eliminate the VMware Tools requirement.
But you still need PowerCLI and network connectivity inside the Guest OS


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

0 Kudos
StephenMoll
Expert
Expert

You could try running something like this in a PowerCLI session connected to your vCenter:

foreach ($VM in Get-VM)
    {
        try { $VMName = $VM | Get-AdvancedSetting -Name "GuestInfo.VMName" }
            catch { $VMName = "" }
    
        if ($VMName) { $VMName | Set-AdvancedSetting -Value "$VM.Name" -Confirm:$false }
            else { $VM | New-AdvancedSetting -Name "GuestInfo.VMName" -Value "$VM.Name" -Confirm:$false }
    }

 

I haven't been able to try this on an actual system yet, but hope that this would create or set an Advanced Setting called "GuestInfo.VMName" to be the name of each VM used in vCenter for each VM respectively.

 

Then with PowerShell inside the guest you can use something like:

$VMName = $(& 'C:\Program Files\VMware\VMware Tools\vmtoolsd.exe' --cmd "info-get guestinfo.VMName" | Out-String) -replace "`t|`n|`r",""

 

If $VMName comes back as empty string, it may be because the GuestInfo.VMName key/variable does not exist. You can check the variable $LASTEXITCODE, which stores the exit code of the last run command. If this is "1" then the variable didn't exist, if it is "0", then the variable did exist and the value in $VMName is valid. 

This should set $VMName to the value of GuestInfo.VMName, which will for all your VMs be the name of the VM known in vCenter.

You would have to remember to re-run the first script if anything is done in vSphere that could alter the name of a VM, or a VM is re-deployed or replaced in some way.

0 Kudos
LucD
Leadership
Leadership

I'm afraid that 1st snippet will not work.

Only the New-AdvancedSetting cmdlet will trigger a non-terminating exception when the guestinfo key already exists.
The Get-AdvancedSetting cmdlet will not trigger an exception when the guestinfo key doesn't exist.

The order of the Try-Catch should be the reverse, and you should add the ErrorAction Stop on the New-AdvancedSetting cmdlet.

And when using a string substitution with a property of an object in a variable, you should use the $($obj.Property) notation.
Your code will set a Value of "<VMname>.Name" I'm afraid.

Get-VM -PipelineVariable vm |
ForEach-Object -Process {
    Try {
        New-AdvancedSetting -Entity $vm -Name "GuestInfo.VMName" -Value $vm.Name -Confirm:$false -ErrorAction Stop
    } Catch {
        Get-AdvancedSetting -Entity $vm -Name "GuestInfo.VMName" |
        Set-AdvancedSetting -Value $vm.Name -Confirm:$false
    }
}

 
But besides the Key and the Value that was the code I already posted in my earlier reply


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

0 Kudos