Saturday, 11 June 2016

Bulk IP Address change with PowerCLI

Recently I was given an interesting task on IP Renumbering of more than a hundred VMs.
Along the IP Address change the VMs had to be moved to a new PortGroup.

Doing it manually can be pretty tiresome and boring. The PowerCLI is a perfect option for this task as it relies on leveraging of VMware Tools. Therefore, loosing network connectivity to the VM due to the IP Address change or after the VM is moved to another Portgroup won't impact the functionality of the script.

Prior running the script you will need to prepare the CSV file with the list of VMs to be updated and the following information for each VM: ServerName, Username, Password, NewPortgroup, OrigIP, NewIP, NewMask, NewGateway

Here is how my Inventory.csv file looks like.



When running the script you will need to provide the path to CSV file and the name of your vCenter

ChangeIP.ps1 -Inventory c:\Scripts\inventory.csv - VC lab-vc-01.lab.local


And here is the script text. Hopefully there are enough comments to help you read the script so that you could adjust it to your needs.

param([String]$Inventory, [String]$VC)
# Getting credentials
do {
$user = Read-Host -Prompt 'Enter username for source vCenter'
$pass = Read-Host -AsSecureString -Prompt 'Enter password for source vCenter'
$cont = Read-Host -Prompt 'Type y to continue'
} while($cont -ne 'y')
$cred = New-Object –TypeName System.Management.Automation.PSCredential –ArgumentList $user, $pass
# Connecting to vCenter
Write-Host 'Connecting to' $VC '..'
Connect-VIServer -Server $VC -Credential $cred | Out-Null
#Ensure you are connected to the correct vCenter
if(!$DefaultVIServer -or $DefaultVIServer.Name -ne $VC) {
Write-Host -Fore:Red 'Connection to vCenter' $SourceVC 'failed, exiting..'
exit
} else {
Write-Host 'Connection to vCenter' $SourceVC 'succeeded'
Write-Host
}
# Processing CSV. You need the following columns in the CSV file: ServerName, Username, Password, NewPortgroup,origIP,newIP,newMask,newGateway
$csv = @()
$csv = Import-CSV -Path $Inventory | Where {$_.ServerName}
$csv | % {
$_.ServerName = $_.ServerName.Trim()
$_.Username = $_.Username.Trim()
$_.Password = $_.Password.Trim()
$_.NewPortgroup = $_.NewPortgroup.Trim()
$_.origIP = $_.origIP.Trim()
$_.newIP = $_.newIP.Trim()
$_.newMask = $_.newMask.Trim()
$_.newGateway = $_.newGateway.Trim()
}
# Updating VMs' Portgroups and IP Addresses
foreach ($vm in $csv){
#Check if the Portgroup exists. Get the correct PG in case there is more than one PG with identical name
$PG= get-virtualswitch -VM $vm.ServerName | get-virtualportgroup | ?{$_.Name -eq $vm.NewPortgroup}
if(!$PG){
Write-Host -Fore:Red "The Portgroup" $vm.NewPortgroup "was not found. Proceeding to the next VM"
Continue
}
#Change Portgroup
Write-Host -Fore:Yellow "Connecting" $vm.ServerName "to Portgroup" $vm.NewPortgroup
$nic = (get-vm -name $vm.ServerName) | get-NetworkAdapter
Set-NetworkAdapter -NetworkAdapter $nic -Portgroup $PG -Confirm:$false
# Changing IP Address
# Check if VM is powered on and if it has the VMtools running
if($vm.PowerState -eq 'PoweredOff' -or $vm.ExtensionData.Guest.ToolsRunningStatus -eq 'guestToolsNotRunning') {
Write-Host -Fore:Red $VM ' is powered off and the IP address of the VM cannot be updated'
} else {
# Check if Guest OS is Windows 2012
if ((Get-vm -name $vm.Servername).Guest.OSFullName -eq "Microsoft Windows Server 2012 (64-bit)"){
# Get the Interface Name
$script = '(Get-NetIPAddress | where-object {$_.IPAddress -match "' + $vm.origIp + '" -and $_.AddressFamily -eq "IPv4"}).InterfaceAlias'
$InterfaceName = invoke-vmscript -ScriptText $script -ScriptType PowerShell -VM $vm.ServerName -GuestUser $vm.Username -GuestPassword $vm.Password
$InterfaceName = $InterfaceName -replace "`t|`n|`r",""
if(!$InterfaceName) {
Write-Host -Fore:Red "The Interface with IP Address" $vm.origIP " was not found in VM" $vm.ServerName "`n"
Continue
}
#Change the IP Address
Write-host -Fore:Yellow "`nChanging IP Address of" $vm.ServerName "interface" $InterfaceName "from" $vm.origIp "to" $vm.newIp
$changingIp = '%WINDIR%\system32\netsh.exe interface ipv4 set address name="' + $InterfaceName + '" source=static address=' + $vm.newIP + ' mask=' + $vm.newMask + ' gateway=' + $vm.newGateway + ' gwmetric=1 store=persistent'
$setIp = invoke-vmscript -ScriptText $changingIp -ScriptType bat -VM $vm.ServerName -GuestUser $vm.Username -GuestPassword $vm.Password
}
# For all other Windows Guest OS types
else {
# Get the Interface Name
$InterfaceName = Get-VMGuestNetworkInterface -VM $vm.ServerName -GuestUser $vm.Username -GuestPassword $vm.Password | where {$_.IP -match $vm.OrigIP}
if(!$InterfaceName) {
Write-Host -Fore:Red "The Interface with IP Address" $vm.origIP " was not found in VM" $vm.ServerName "`n"
Continue
}
#Change the IP Address
Write-host -Fore:Yellow "`nChanging IP Address of" $vm.ServerName "interface" $InterfaceName "from" $vm.origIp "to" $vm.newIp
Set-VMGuestNetworkInterface -VMGuestNetworkInterface $InterfaceName -GuestUser $vm.Username -GuestPassword $vm.Password -Ip $vm.NewIP -Netmask $vm.NewMask -Gateway $vm.NewGateway
}
# Register the new IP Address with DNS
Write-Host -Fore:Yellow "Registering with DNS"
$registeringDNS = '%WINDIR%\System32\ipconfig /registerdns'
$segDNS = invoke-vmscript -ScriptText $registeringDNS -ScriptType bat -VM $vm.ServerName -GuestUser $vm.Username -GuestPassword $vm.Password
Write-Host -Fore:Green $vm.ServerName "has been sucessfully updated `n"
}
}
Disconnect-VIServer -Confirm:$false
view raw ChangeIP.ps1 hosted with ❤ by GitHub