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.




  • 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 = $
    $ip = $_.ip

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

#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