Another one from the PowerCLI Community. User internetrush1 wanted to know how he could rename an ESXi server through PowerCLI.
In fact I was amazed there obviously is no cmdlet nor scripts available to perform this rather basic task. Luckily I had some code snippets laying around that did the job. Basically, I followed KB1010821 to do the ESXi 5.x host rename. But I decided it would be better to provide a real function to do the job.
The Script
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 |
function Rename-VMHost { <# .SYNOPSIS Renames an ESXi server .DESCRIPTION The function will rename an ESXi 5.x server. The function follows VMware KB1010821 .NOTES Author: Luc Dekens .PARAMETER VMHost The ESXi server to be renamed .PARAMETER Credential The credentials to connect to the ESXi 5.x server .PARAMETER NewName The new FQDN .PARAMETER Location By default the ESXi server will stay in its current location. You can specify a Datacenter or Cluster for the newly named ESXi 5.x server. .PARAMETER MaintenanceMode Although not required by KB1010821, by default the function places the ESXi 5.x server in maintenance mode, before doing the rename. .PARAMETER DnsCheck When this switch is set, the function will first check if the new name for the ESXi host can be resolved with DNS. .EXAMPLE PS> Rename-VMHost -VMHost $esx -NewName "newname.lucd.info" #> [CmdletBinding()] param( [PSObject]$VMHost, [System.Management.Automation.PSCredential]$Credential, [string]$NewName, [PSObject]$Location, [Switch]$MaintenanceMode = $true, [Switch]$DnsCheck ) Process { if($DnsCheck){ Try { [System.Net.Dns]::GetHostEntry($NewName).HostName | Out-Null } Catch { Write-Error "No DNS entry for $NewName" return } } $vCenterName = $global:DefaultVIServer.Name if($VMHost -is [System.String]){ $VMHost = Get-VMHost -Name $VMHost } if($Location){ if($Location -is [System.String]){ $Location = Get-Inventory -Name $Location } } else { $Location = $VMHost.Parent } if($Location -isnot [VMware.VimAutomation.ViCore.Impl.V1.Inventory.ClusterImpl] -and $Location -isnot [VMware.VimAutomation.ViCore.Impl.V1.Inventory.DatacenterImpl]){ Write-Error "Location $($Location.Name) must be a datacenter or a cluster" return } if($MaintenanceMode){ $previousState = $VMHost.State Set-VMHost -VMHost $VMHost -State Maintenance | Out-Null } Set-VMHost -VMHost $VMHost -State Disconnected -Confirm:$false | Remove-VMHost -Confirm:$false | Out-Null $esxServer = Connect-VIServer -Server $VMHost.Name -Credential $Credential $esxcli = Get-EsxCli -Server $esxServer $esxcli.system.hostname.set($null,$NewName,$null) Disconnect-VIServer -Server $esxServer -Confirm:$false Connect-VIServer -Server $vCenterName | Out-Null $VMHost = Add-VMHost -Name $NewName -Location $Location -Credential $Credential -Force -Confirm:$false if($MaintenanceMode){ Set-VMHost -VMHost $VMHost -State $previousState -Confirm:$false | Out-Null } } } |
Annotations
Line 40-48: The function checks if the new hostname can be resolved. If not the function returns.
Line 51-53: Cheap Object By Name (OBN) implementation
Line 54-66: The ESXi will be added to the location specified in the $Location variable. This can be a Datacenter or a cluster. If no Location value is passed, the host is added to the same location where it was before the rename.
Line 68-71: Although not required (see also KB1010821), the host that will be renamed is placed in maintenance mode by default. The switch to maintenance mode will vMotion all VMs to other nodes in the cluster.
Line 72-73: The ESXi host is disconnected and removed from the vCenter.
Line 75-78: The function uses the Get-EsxCli cmdlet to be able to call the rename method. Note that the function at this point will close the vCenter connection, and connect directly to the ESXi host.
Line 80-81: After the rename, the ESXi host is added to the vCenter in it’s old location or the location that was explicitely specified on the function call.
Line 83-85: When required, the ESXi host is taken out of maintenance mode, and placed in the mode it was in originally.
Sample Usage
The use of this function is quite simple.
In it’s easiest form, you provide the VMHost, the new name and the credentials.
1 2 3 4 5 6 7 8 9 10 |
$oldName = "esx1.local.test" $newName = "esx2.local.test" $username = "root" $pswd = "password" $pswdSecure = ConvertTo-SecureString -String $pswd -AsPlainText -Force $cred = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $username,$pswdSecure Rename-VMHost -VMHost $oldName -NewName $newName -Credential $cred |
The ESXi host, called esx1.local.test will be renamed to esx2.local.test. The function will test if the new name is resolvable by DNS, and it will place the ESXi host in maintenance mode before the rename is done.
Note that I only tested this function on ESXi 5.x hosts.
Enjoy !
Vasil Nedelchev
This script works for 6.x, 7.x:
#Set-PowerCLIConfiguration -InvalidCertificateAction:Ignore
Connect-VIServer -Server {{serverName}} -Protocol https -User {{userName}} -Password {{password}}
$newFqdn = “esx-01a.test.local”
$oldFqdn = “esx-01b.test.local”
$newHostName = “esx-01a”
$newDomainName = “test.local”
Get-VMHost $oldFqdn | Get-View | % {
$_.DisconnectHost();
$_.ReconnectHost((New-Object VMware.Vim.HostConnectSpec -property @{HostName = $newFqdn }), $null);
(Get-View $_.ConfigManager.NetworkSystem).UpdateDnsConfig((New-Object VMware.Vim.HostDnsConfig -Property @{HostName = $newHostName; DomainName = $newDomainName; dhcp = $false }))
}
LucD
Thanks for sharing that.
JD
LucD…. did you ever get around to rewriting this to use Reubens ReconnectHost method?
RB
great post and very useful..
I am trying to write a foreach script to change each host from lower case to upper case, but not quite getting there.. If you have any ideas it would be great to hear from you.
Reuben Stump
LucD, I caught your post and it reminded me of a trick to actually rename hosts in vCenter without having to remove them (preserves the historical information – tasks, events, performance counters, custom values, etc).
I hope you don’t mind, but I linked to your post and explain how to do the non-destructive rename workflow. Mine is in Perl (as always), but I think it would be pretty easy to modify your PowerCLI function to run the same process and avoid the remove from inventory step in the process.
https://www.virtuin.com/2013/12/rename-esxi-hosts-in-vcenter-without.html
Thanks!
LucD
Hi Reuben, great info, I didn’t know that one.
Renaming an ESXi host without loosing any historical data is indeed much better in most cases.
I’ll update my function to optionally use the ReconnectHost method.
Chris Stephens
The ‘if’ statement on line 36 will never be true, as there is no parameter or variable declaration elsewhere in the script. Therefore, the DNS resolution check will never occur.
LucD
Thanks for noticing that Chris.
I updated the script, the switch and the help entry has been added.
internetrush1
Mofified the script:
function Rename-VMHost {
Rename-VMHost -VMHost $esx -NewName “newname.lucd.info”
#>
[CmdletBinding()]
param(
[Parameter(Mandatory=$True,Position=1)]
$VMHost,
[Parameter(Mandatory=$True,Position=2)]
[System.Management.Automation.PSCredential]$RootCredential,
[Parameter(Mandatory=$True,Position=3)]
[string]$NewName,
[Parameter(Mandatory=$True,Position=4)]
$Location,
[Switch]$MaintenanceMode = $false,
[Parameter(Mandatory=$True,Position=5)]
[System.Management.Automation.PSCredential]$DomainCredential
)
Process {
if([string]::isnullorempty($global:DefaultVIServer)){Connect-VIServer -Server (Read-Host “Enter vCenter Server”) -Credential $DomainCredential | Out-Null -ErrorAction ‘Stop’}
$vCenterName = $global:DefaultVIServer.Name
if($VMHost -is [System.String]){
$VMHost = Get-VMHost -Name $VMHost
}
if($Location){
if($Location -is [System.String]){
$Location = Get-Inventory -Name $Location
}
}
else {
$Location = $VMHost.Parent
}
if($Location -isnot [VMware.VimAutomation.ViCore.Impl.V1.Inventory.ClusterImpl] -and
$Location -isnot [VMware.VimAutomation.ViCore.Impl.V1.Inventory.DatacenterImpl]){
Write-Error “Location $($Location.Name) must be a datacenter or a cluster”
return
}
if($VMHost.state -ne ‘Disconnected’){
$previousState = $VMHost.State
Set-VMHost -VMHost $VMHost -State ‘Maintenance’ -ErrorAction ‘Stop’
Set-VMHost -VMHost $VMHost -State ‘Disconnected’ -Confirm:$false -ErrorAction ‘continue’ | Remove-VMHost -Confirm:$false -ErrorAction ‘stop’
}
$esxServer = Connect-VIServer -Server $VMHost.Name -Credential $RootCredential
$esxcli = Get-EsxCli -Server $esxServer
$esxcli.system.hostname.set($null,$NewName,$null)
Disconnect-VIServer -Server $esxServer -Confirm:$false
$oldName = $vmhost.name
#make sure DNS entry is correct
try{
$newDNSName = ([System.Net.Dns]::GetHostEntry($NewName).HostName)
}catch{
$ip = ([System.Net.dns]::GetHostAddresses($oldname) | select IPAddressToString).IPAddressToString
Read-Host “Please CHANGE the DNS Entry at: $ip for: $oldName to: $newname hit enter when ready”
[int]$i = 0
do{
Write-Host “Waiting $i seconds until dns returns true”
$remoteServer = [System.Net.Dns]::GetHostEntry($vcentername).HostName
invoke-command -ComputerName $remoteServer -Credential $DomainCredential -ScriptBlock {ipconfig /flushdns}
try{
$VMHost = Add-VMHost -Name $NewName -Location $Location -Credential $RootCredential -Force -Confirm:$false -ErrorAction ‘Stop’
$continueTest = $false
}catch{
Write-Host “ERROR ADDING HOST : $_”
$continueTest = $true
}
}while($continueTest)
}
if(!$MaintenanceMode){
Set-VMHost -VMHost $VMHost -State $previousState -Confirm:$false -ErrorAction ‘silentlyContinue’ | Out-Null
}else{
Set-VMHost -VMHost $VMHost -State ‘Maintenence’ -Confirm:$false -ErrorAction ‘silentlyContinue’ | Out-Null
}
}
}
LucD
Thanks, that is a useful addition.
Davoud Teimouri
Great post. Thanks.