Skip navigation
2013

Amitrajit Chatterjee's Blog

October 2013 Previous month Next month

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)