Skip navigation

Sometimes it might be necessary to do a mass change of all the IPs of all the vms, specially if the underlying infrastructure is being moved to a different datacenter. Along with the IPs the vlans might change. This is a script where new network labels have been created on a distributed switch and all the vms will need to be updated to the new label and IP. I found it easier to first update the IP and then the label instead of the other way round.

 

  • First a CSV file (list.csv) containing list of servers to be updated. It has the Name of the vm, the new IP, the Gateway address and the new Network label already created in the Vcenter server. Assuming that it's a /24 network address space, the subnet mask of 255.255.255.0 is hard-coded in the script. Different IPs can be part of the same script. The DNS server IPs are also hard-coded in.

 

name,ip,gw,label
server01,10.10.100.10,10.10.100.1,VMNet_100
server02,10.10.100.11,10.10.100.1,VMNet_100
server03,10.10.100.12,10.10.100.1,VMNet_100
server04,10.10.100.13,10.10.100.1,VMNet_100
server05,10.10.100.14,10.10.100.1,VMNet_100
server06,10.10.200.10,10.10.200.1,VMNet_200
server07,10.10.200.11,10.10.200.1,VMNet_200
server08,10.10.200.12,10.10.200.1,VMNet_200
server09,10.10.200.13,10.10.200.1,VMNet_200
server10,10.10.200.14,10.10.200.1,VMNet_200

 

  • And here is the actual Windows Powershell script. To run from  vSphere PowerCLI, remove "Add-PSSnapin VMware.VimAutomation.Core" at the beginning of the code. After powering on the vms, it sends out an email with the list of vms.

 

  • It first checks if VMware Tools are running on the vm. All vms will need VMware Tools installed and running else the script will skip that vm and the name of the vm will be added to "issues.txt" file. Successful names will be added to "report.txt" file.

 

  • This assumes the vm has only one nic. Also do not include VCenter server in the list, that IP should be changed manually.
#Add-in necessary modules
Add-PSSnapin VMware.VimAutomation.Core
Set-PowerCLIConfiguration -InvalidCertificateAction ignore -ProxyPolicy NoProxy -Confirm:$False

#Connect to vcenter server
$vcenter = "<FQDN or IP of vcenter server>"
connect-viserver $vcenter

#Import list of vms
Import-csv C:\list.csv |
foreach {
    $computer = $_.name
    $ip = $_.ip
    $gw = $_.gw
    $label = $_.label

    #Check if VMware Tools are running in the vm without which most of the following commands will not work
    $toolstatus = (Get-VM $computer | Get-View).Guest.ToolsStatus
    if ($toolstatus -eq 'toolsOk'){
        Write-Host (Get-Date).DateTime
        Write-Host -ForegroundColor Green "$computer is up."

        #Read current network settings, needs Domain Admin credentials
        $vmguestnic = Get-VM -Name $computer | Get-VMGuestNetworkInterface -GuestUser '<Domain Admin>' -GuestPassword '<Domain Admin Password>'  -ToolsWaitSecs 30
     
        #Add current network settings to local text file
        Write-Host -ForegroundColor Green "Current network settings are being added to report.txt file."

        "`r`n`r`n"+ (Get-Date).DateTime + "`r`n Current settings:  " +$computer+", "+ $vmguestnic.Ip +", "+$vmguestnic.DefaultGateway | Out-File C:\report.txt -Append

        #Set new IP settings, needs Domain Admin credentials. Double check Subnet Mask and DNS IPs.
        Set-VMGuestNetworkInterface -GuestUser '<Domain Admin>' -GuestPassword '<Domain Admin Password>' -VmGuestNetworkInterface $vmguestnic -IPPolicy Static -Ip $ip -Gateway $gw -Netmask 255.255.255.0 -Dns 10.10.10.2,10.10.10.3
        Write-Host -ForegroundColor Green "Changing IP address."

        #Change port group label which needs to be created before-hand in the Vcenter server.
        Write-Host -ForegroundColor Green "Changing network label."
        Get-VM -Name $computer | Get-NetworkAdapter  | Set-NetworkAdapter -NetworkName $label -connected:$true -StartConnected:$true -confirm:$false

        #Ping the server till it's successful
        do {
            Write-Host -ForegroundColor Green "Could not ping server $computer, sleeping for 5 seconds."
            sleep 5
        } while (((Get-WmiObject win32_pingstatus -Filter "address='$ip'").statuscode) -eq 1)

        #Add current network settings to report text file
        Write-Host (Get-Date).DateTime
        Write-Host -ForegroundColor Green "$computer ping was successful, writing new settings to report.txt file."
        "`r`n New Settings" | Out-File C:\report.txt -Append
        $nic = Get-VM -Name $computer | Get-VMGuestNetworkInterface -GuestUser '<Domain Admin>' -GuestPassword '<Domain Admin Password>'  | Select Ip,SubnetMask,DefaultGateway,Dns,Mac
        $nic | Out-File C:\report.txt -Append
        (Get-Date).DateTime | Out-File C:\report.txt -Append
        "`r`n-------------------------------------------------------------------------------------------------------------"| Out-File C:\report.txt -Append

     } else {
        Write-Host (Get-Date).DateTime
        Write-Host -ForegroundColor Green "$computer - cannot ping server, check if it's running. "
        #Add server to issue text file
        "`r`n" + (Get-Date).DateTime + "`r`n" + $computer | Out-File C:\issues.txt -Append
    }
}

#Disconnect from vcenter server
Disconnect-viserver $vcenter -Confirm:$False



If for some reason vmotion is not available in the environment and a large number of vms need to be migrated from one host to another (specially when they are of different versions), then the following script can be used. It will check the power state of the vm, power it off if needed and then migrate it. I have a separate script to power on vms.  That can also be included at the bottom of this one. They both read of the same list.

 

  • First a CSV file (poweredonvms.csv) containing list of servers to be migrate.
name
vmserver01
vmserver02
vmserver03
vmserver04
vmserver05
vmserver06
vmserver07
vmserver08
vmserver09
vmserver10

 

  • And here is the actual Windows Powershell script. To run from  vSphere PowerCLI, remove "Add-PSSnapin VMware.VimAutomation.Core" at the beginning of the code. After shutting off the vms and migrating them, it sends out an email with the list of vms.
  • It first checks if a vm is powered off, if yes it gets migrated. If not it checks the status of VMware Tools, depending upong which the vm can be gracefully shutdown or forced to shutdown. The list will show which method was used.
Add-PSSnapin VMware.VimAutomation.Core

$vcenter="vcenter.domain.local"

#Connect to vcenter server
connect-viserver $vcenter

#Import vm name and ip from csv file
Import-Csv poweredonvms.csv |
foreach {
    $strNewVMName = $_.name
  
    #Generate a view for each vm to determine power state
    $vm = Get-View -ViewType VirtualMachine -Filter @{"Name" = $strNewVMName}
  
           if ($vm.Runtime.PowerState -eq "PoweredOff") {
               if ($vm.config.Tools.ToolsVersion -ne 0) {
                   Write-Host "Powered off. Moving VM ++++++ $strNewVMName ----"
                   Move-VM -Destination <destination host> -VM $strNewVMName -Confirm:$false
                 
                   #For generating email
                   $Report += $strNewVMName + " --- VM powered off and moved. `r`n"
               }
           } else {
            if ($vm.config.Tools.ToolsVersion -ne 0) {
                   Write-Host "VMware tools installed. Graceful OS shutdown ++++++++ $strNewVMName ----"
                   Shutdown-VMGuest $strNewVMName -Confirm:$false
                Sleep 120
                   Move-VM -Destination <destination host> -VM $strNewVMName -Confirm:$false
                   #For generating email
                   $Report += $strNewVMName + " --- VMware tools installed. Graceful OS shutdown and vm moved. `r`n"
               }
               else {
                   Write-Host "VMware tools not installed. Force VM shutdown ++++++++ $strNewVMName ----"
                Stop-VM $strNewVMName -Confirm:$false
                Sleep 60
                Move-VM -Destination <destination host> -VM $strNewVMName -Confirm:$false             
                #For generating email
                   $Report += $strNewVMName + " --- VMware tools not installed. Force VM shutdown and vm moved. `r`n"
              
               }
         }
}

write-host "Sleeping ..."
Sleep 30

#Send out an email with the names
$emailFrom = "noreply@domain.com"
$emailTo = "noreply@domain.com"
$subject = "List of vms migrated"
$smtpServer = "smtp server"
$smtp = new-object Net.Mail.SmtpClient($smtpServer)
$smtp.Send($emailFrom, $emailTo, $subject, $Report)

#Disconnect to vcenter server
disconnect-viserver $vcenter -Confirm:$false


This is a simple way of adding memory to a powered-on vm, which has the Memory hot plug option enabled. It reads the server names from a file (deploy.csv) and updates the memory to what is specified in the script.

  • First the deploy.csv file
name
vmserver01
vmserver02

 

  • Actual script, MemoryMB needs to be updated
#Connect to vcenter server
connect-viserver vcenter.domain.local

#Import vm name and ip from file
Import-Csv deploy.csv |
foreach {
    $strNewVMName = $_.name
    
    write-host "Server ----- $strNewVMName" 
    
    #MemoryMB needs to change
    Set-VM -VM $strNewVMName -MemoryMB 6144
    Sleep 2    
    Get-VM -name $strNewVMName | Select Name, MemoryGB
    
    $Report += $strNewVMName 
}

write-host "Sleeping ..."  
Sleep 10

#Send out an email with the names
$emailFrom = "<from email id>"
$emailTo = "<to email id>"
$subject = "List of servers with upgraded memory"
$smtpServer ="<smtp server name>"
$smtp = new-object Net.Mail.SmtpClient($smtpServer)
$smtp.Send($emailFrom, $emailTo, $subject


, $Report)

There are many articles on the web about how to clone VMs and customise them. Below is a simple way of doing it. The script creates multiple clones from a VM template, customises them and assigns names and ip from a file. This assumes there is a Datastore Cluster being used, else during creating vms the name of the datastore where new vm should be placed will need to be specified.

 

  • First a CSV file (deploy.csv) containing list of servers and the ip addresses.

 

name,ip
vmserver01,10.10.10.1
vmserver02,10.10.10.2
vmserver03,10.10.10.3
vmserver04,10.10.10.4
vmserver05,10.10.10.5
vmserver06,10.10.10.6
vmserver07,10.10.10.7
vmserver08,10.10.10.8
vmserver09,10.10.10.9
vmserver10,10.10.10.10








 

  • Create a template of the vm called "VM_Template".
  • Create a Customisation Specification file called "VM_Custom".
    • For the Network section select "Custom Settings".
    • For Network Properties under IP Address select DHCP (even though later on it will be changed to static ip.
    • This assumes there is a Datastore Cluster being used so Storage DRS decides where the new vm will be placed.
    • Also the ESXi host where the new vm will be placed is randomly selected from host cluster.

 

#Connect to vcenter server
connect-viserver <vcenter server>

#Template name
$strTemplate = "VM_Template"

#Customisation settings name
$strCustomSpec = "VM_Custom"

#Specify Datastore cluster
$myDatastoreCluster = Get-DatastoreCluster -Name <Datastore Cluster Name>

#Import vm name and ip from csv file
Import-Csv deploy.csv |
foreach {
    $strNewVMName = $_.name
    $ip = $_.ip

    #Use existing customisation file but change the IP
    $spec = Get-OSCustomizationSpec $strCustomSpec | Get-OSCustomizationNicMapping | Set-OSCustomizationNicMapping -IpMode UseStaticIp  -IpAddress $ip -SubnetMask 255.255.255.0 -DefaultGateway 10.10.10.100 -Dns 10.10.10.101,10.10.10.102

#Placement on random hosts
    $vmhost = Get-Cluster <cluster name> | Get-VMHost | Get-Random | Where{$_ -ne $null}

    write-host "Build started ++++++++ $strNewVMName ------ $ip "

    New-VM -Name $strNewVMName -Template $(get-template $strTemplate) -Datastore $myDatastoreCluster -VMHost $vmhost | Set-VM -OSCustomizationSpec $spec -Confirm:$false | Start-VM

    write-host "Build completed ++++++++ $strNewVMName ------ $ip "

    $Report += $strNewVMName
}

write-host "Sleeping ..."
Sleep 300

#Send out an email with the names
$emailFrom = "<sender email id>"
$emailTo = "<recipient email id>"
$subject = "List of servers built"
$smtpServer = "<smtp server name>"
$smtp = new-object Net.Mail.SmtpClient($smtpServer)
$smtp.Send($emailFrom, $emailTo, $subject, $Report)

#Disconnect from vcenter server
disconnect-viserver $vcenter -Confirm:$false



There are many articles on the web about how to shutdown and poweron VMs with a script. My version of powering off VMs is here. Below is the script for powering on a list of VMs.

 

  • First a CSV file (poweredonvms.csv) containing list of servers to be updated. It can also be generated automatically by the powering off vm script.

 

name
vmserver01
vmserver02
vmserver03
vmserver04
vmserver05
vmserver06
vmserver07
vmserver08
vmserver09
vmserver10

 

 

  • And here is the actual Windows Powershell script. To run from  vSphere PowerCLI, remove "Add-PSSnapin VMware.VimAutomation.Core" at the beginning of the code. After powering on the vms, it sends out an email with the list of vms.
  • It first checks if a vm is powered on. If it is powered on already, it will be skipped. Else it will be powered on.
Add-PSSnapin VMware.VimAutomation.Core

$vcenter="<vcenter server>"

#Connect to vcenter server
connect-viserver $vcenter

#Import vm name and ip from csv file
Import-Csv poweredonvms.csv |
foreach {
    $strNewVMName = $_.name

    #Generate a view for each vm to determine power state
    $vm = Get-View -ViewType VirtualMachine -Filter @{"Name" = $strNewVMName}
   
    if ($vm.Runtime.PowerState -ne "PoweredOn") {
          
            Write-Host "Powering On $strNewVMName ----"
            Get-VM $strNewVMName | Start-VM
            Sleep 10
                                      
        #For generating email
               $Report += $strNewVMName + " --- Powered on. `r`n"
          
     }
}

write-host "Sleeping ..."
Sleep 300

#Send out an email with the names
$emailFrom = "<sender email id>"
$emailTo = "<recipient email id>"
$subject = "List of servers powered on"
$smtpServer = "<smtp server name>"
$smtp = new-object Net.Mail.SmtpClient($smtpServer)
$smtp.Send($emailFrom, $emailTo, $subject, $Report)

#Disconnect to vcenter server
disconnect-viserver $vcenter -Confirm:$false

There are many articles on the web about how to shutdown and poweron VMs with a script. My version of powering on VMs is here. Here is the script for powering off a list of VMs.

 

  • First a CSV file (poweredonvms.csv) containing list of servers to be updated.

 

name
vmserver01
vmserver02
vmserver03
vmserver04
vmserver05
vmserver06
vmserver07
vmserver08
vmserver09
vmserver10



 

  • And here is the actual Windows Powershell script. To run from  vSphere PowerCLI, remove "Add-PSSnapin VMware.VimAutomation.Core" at the beginning of the code. After shutting off the vms, it sends out an email with the list of vms.
  • It first checks if a vm is powered on and if it has VMware Tools are installed. If vm is powered off already, it will be skipped. If VMware Tools are installed, there will be graceful shutdown of the guest OS else there will be a hard shutdown. The list will show which method was used.

 

Add-PSSnapin VMware.VimAutomation.Core

$vcenter="<vcenter name>"

#Connect to vcenter server
connect-viserver $vcenter

#Import vm name from csv file
Import-Csv E:\Scripts\power\poweredonvms.csv |
foreach {
    $strNewVMName = $_.name

    #Generate a view for each vm to determine power state
    $vm = Get-View -ViewType VirtualMachine -Filter @{"Name" = $strNewVMName}

    #If vm is powered on then VMware Tools status is checked
           if ($vm.Runtime.PowerState -ne "PoweredOff") {
               if ($vm.config.Tools.ToolsVersion -ne 0) {

                   Write-Host "VMware tools installed. Graceful OS shutdown ++++++++ $strNewVMName ----"
                   Shutdown-VMGuest $strNewVMName -Confirm:$false
                
                   #For generating email
                   $Report += $strNewVMName + " --- VMware tools installed. Graceful OS shutdown `r`n"
               }
               else {

                      Write-Host "VMware tools not installed. Force VM shutdown ++++++++ $strNewVMName ----"
                      Stop-VM $strNewVMName -Confirm:$false
                            
                   #For generating email
                   $Report += $strNewVMName + " --- VMware tools not installed. Force VM shutdown `r`n"
               }
           }
}

write-host "Sleeping ..."
Sleep 300

#Send out an email with the names
$emailFrom = "<sender email id>"
$emailTo = "<recipient email id>"
$subject = "List of servers shutdown for maintenance"
$smtpServer = "<smtp server name>"
$smtp = new-object Net.Mail.SmtpClient($smtpServer)
$smtp.Send($emailFrom, $emailTo, $subject, $Report)

#Disconnect vcenter server
disconnect-viserver $vcenter -Confirm:$false



There are many articles on the web about how to update VMware Tools of virtual machines, without a reboot. Here is my take on it. Simple, dirty code.

 

  • First a CSV file (deploy.csv) containing list of servers to be updated.

 

name
vmserver01
vmserver02
vmserver03
vmserver04
vmserver05
vmserver06
vmserver07
vmserver08
vmserver09
vmserver10



 

  • And here is the actual Powershell script, I run it from vSphere PowerCLI. To run from  Windows Powershell, add "Add-PSSnapin VMware.VimAutomation.Core" at the beginning of the code. After updating the vms, it sends out an email with the list of vms updated. Get-Cluster <cluster name> portion can be skipped, if there is only one cluster.

 

#Connect to vcenter server
connect-viserver <vcenter name>

#Import vm name from csv file
Import-Csv deploy.csv |
foreach {
    $strNewVMName = $_.name
    
    #Update VMtools without reboot
    Get-Cluster <cluster name> | Get-VM $strNewVMName | Update-Tools –NoReboot

   write-host "Updated $strNewVMName ------ "
     
    $report += $strNewVMName
}

write-host "Sleeping ..."
Sleep 120

#Send out an email with the names
$emailFrom = "<sender email id>"
$emailTo = "<recipient email id>"
$subject = "VMware Tools Updated"
$smtpServer = "<smtp server name>"
$smtp = new-object Net.Mail.SmtpClient($smtpServer)
$smtp.Send($emailFrom, $emailTo, $subject, $Report)