I couldn’t find a PowerCLI script to clone Linux and assign ip addresses to multiple adapters so I decided to write my own.
If you are new to Vsphere PowerCLI, you may need to check my previous post to learn how to connect to vi-server via PowerCLI at first.
There are 2 scripts:
discover-info.ps1 # Discovery information of target viserver/ESX host and generate template file to be used for clonevm.ps1
vmclone.ps1 #clone after read information from template file generated by discover-info.ps1 script
The scripts has been tested in VMware vSphere PowerCLI 4.0 for VMs in ESX 3.5/ESX4.0 managed by Virtual Center Server.
Scripts in action
[vSphere PowerCLI] D:\Temp> .\discover-info.ps1Discovered ESX hosts:esx01 esx02Please enter target ESX hostname: esx01..Template file: vmdata.txt has been generated. Edit the file then run 'clonevm.ps1 -f file-name' to start cloning[vSphere PowerCLI] D:\Temp> cat vmdata.txt (after customization)============####---------------- Discovered information#PortGroups='Service Console' 'vlan-01' 'vlan-02'#Folders='host' 'Discovered Virtual Machine' 'Datacenters' 'vm'#DataStores= 'nfs_storage' 'esx01:storage1'#resourcepools=Name: Resources ID:ResourcePool-resgroup-7 Name: Resources ID:ResourcePool-resgroup-65####----------------####----------------Customize your VM values using the templateesxhost=esx01##Resource pool id is NOT required for using virtual machine as source, but IS required for using template as source#resourcepoolid=#vm means Virtual Machine; vt means template ( resourcepoolid is required for vt)SrcName=vm,linuxtemplateDstName=pstest1##Use vm as folder if no user folders definedFolder=vmDataStore=nfs_storage##Gateway is optional, enter - to skip this value##Networkadapter type is optional (Auto choosen for guest OS) , enter - to skip this value##Supported adapter types: e.g e1000, Flexible, Vmxnet, EnhancedVmxnetNetwork=EnhancedVmxnet,vlan-01 ,172.19.1.1,255.255.248.0,172.19.1.10 ; -,vlan-02,172.20.1.1,255.255.255.0,-DNS=10.1.1.1,10.1.1.2Domain=example.com#Poweron=yes####----------------[vSphere PowerCLI] D:\Temp> .\clonevm.ps1 -f .\vmdata.txt==> Retrieving info for source VM: linuxtemplate==> Starting clone process ...4% 10% 16% 21% 27% 33% 38% 45% 51% 57% 62% 68% 74% 79% 85% 91% %Completed Task: Task-task-2366==> Checking new VM ...Name PowerState Num CPUs Memory (MB)---- ---------- -------- -----------pstest1 PoweredOff 1 4096==> Removing existing network adapters ...==> Adding 2 new network adapters .....==> Customizing guest OS ...%Completed Task: Task-task-2370==> Checking new VM ...pstest1 PoweredOff 1 4096
Discover-info.ps1 download
# *Execute the script in a live PowerCLI VIsserver session*# Generate template file to be used for clonevm.ps1# DATE: 12 Oct 2010# Author: http://honglus.blogspot.com$template_file="vmdata.txt"$hosts=get-vmhost | foreach { $_.name }write-host "Discovered ESX hosts: $hosts"switch ($hosts.length) {0 { write-host "no ESX host found! exiting.. " ; exit}1 { $esxhost=$hosts[0] }default {$esxhost=read-host "Please enter target ESX hostname"if ( -not $($hosts -contains "$esxhost") ) { write-host "Unknown host: '$esxhost', exiting.. " ; exit }}}$pgs=Get-VirtualPortGroup -vmhost $esxhost | foreach { "'$_'" }$folders=get-folder | foreach { "'$_'" }$dss=get-datastore -vmhost $esxhost | foreach { "'$_'"}$rspool=get-resourcepool | foreach { "Name: " + $_.name + " ID:" + $_.id }write-output "####---------------- Discovered information#PortGroups=$pgs#Folders=$folders#DataStores= $dss#resourcepools=$rspool####----------------####----------------Customize your VM values using the templateesxhost=$esxhost##Resource pool id is NOT required for using virtual machine as source, but IS required for using template as source#resourcepoolid=#vm means Virtual Machine; vt means template ( resourcepoolid is required for vt)SrcName=vm,clone1DstName=guest1##Use vm as folder if no user folders definedFolder=vmDataStore=data_store##Gateway is optional, enter - to skip this value##Networkadapter type is optional (Auto choosen for guest OS) , enter - to skip this value##Supported adapter types: e.g e1000, Flexible, Vmxnet, EnhancedVmxnetNetwork=adapter-type,port-group1,ip-address1,net-mask1,gateway1 ; EnhancedVmxnet,port-group2,ip-address2,net-mask2,gateway2 ; ...DNS=dns1,dns2Domain=example.comPoweron=yes####----------------" | tee $template_filewrite-host "Template file: $template_file has been generated. Edit the file then run 'clonevm.ps1 -f file-name' to start cloning"
clonevm.ps1 download
# *Execute the script in a live PowerCLI VIsserver session*##### Clone VM for Linux guest#Read information from template file generated by discover-info.ps1 script#Set target host/datastore for Clone ;Start Clone#Delete existing adapters; add new adapters; Customize guest OS; powerone VM (Optional)#DATE: 12 Oct 2010#Author: http://honglus.blogspot.comif ( ( $args.count -ne 2 ) -or ( $args[0] -ne "-f" ) ) { write-host "Usage: .\program -f template-filename" ; exit}$file1=$args[1]function Retrieve-Values {$strings=$args[0]$item=$args[1]$line=[string] ($strings | select-string -pattern "$item")$line=$line.trim()return $line.Substring( $line.LastIndexOf("=")+1 )}function wait-for-task {if ( $args[0] -eq $null ) {write-host "failed " ;exit }$tskid=$args[0]$progress=get-task -status running | foreach { if ( $_.id -eq $tskid ) { $_.PercentComplete } }while ( $progress -ne $null ) {sleep 30$progress=get-task -status running | foreach { if ( $_.id -eq $tskid ) { $_.PercentComplete} }write-host "$progress% " -nonewline}write-host ""write-host "Completed Task:" $tskid}$lines=get-content $file1 -ErrorAction stop | select-string -notmatch "(^#|^$)" -ErrorAction stop$s_esxhost=Retrieve-values $lines "esxhost"$s_rspoolid=Retrieve-values $lines "resourcepoolid"$s_srcname=Retrieve-values $lines "SrcName"$s_dstname=Retrieve-values $lines "Dstname"$s_folder=Retrieve-values $lines "Folder"$s_datastore=Retrieve-values $lines "DataStore"$s_domain=Retrieve-values $lines "Domain"$s_network=Retrieve-values $lines "Network"$s_poweron=Retrieve-values $lines "Poweron"$s_dns=Retrieve-values $lines "DNS"$s_dns=$s_dns.split(",")$array_temp=$s_network.split(";")$nic_cnt=$array_temp.count#Initialize hash table$h_network=@{atype=(1..$nic_cnt); pgroup=(1..$nic_cnt); ip=(1..$nic_cnt); mask=(1..$nic_cnt); gateway=(1..$nic_cnt) }For ($i=0; $i -lt $nic_cnt ; $i++) {$array_temp2=$array_temp[$i].split(",")if ( $array_temp2.count -ne 5 ) { write-host "Expected the number of values for network is 5, given" $array_temp2.count ; exit}$h_network.atype[$i]=$array_temp2[0].trim()$h_network.pgroup[$i]=$array_temp2[1].trim()$h_network.ip[$i]=$array_temp2[2].trim()$h_network.mask[$i]=$array_temp2[3].trim()$h_network.gateway[$i]=$array_temp2[4].trim()}$vmclonespec_host = New-Object VMware.Vim.VirtualMachineCloneSpec#### Customize Target host /Target datastore$vmclonespec_host.location = New-Object VMware.Vim.VirtualMachineRelocateSpec$vmclonespec_host.location.host = (Get-vmHost -Name $s_esxhost | Get-View).MoRef$vmclonespec_host.location.datastore = (Get-Datastore -Name $s_datastore| Get-View).MoRefif ( $s_rspoolid.length -gt 0 ) {$vmclonespec_host.location.pool= (Get-ResourcePool -id $s_rspoolid -ErrorAction stop|get-view).MoRef}#### Customize Guest OS$vmclonespec_os= New-Object VMware.Vim.CustomizationSpec## Identity for Linux$vmclonespec_os.identity= New-Object VMware.Vim.CustomizationLinuxPrep$vmclonespec_os.identity.hostname= New-Object VMware.Vim.CustomizationFixedName$vmclonespec_os.identity.hostname.name= $s_dstname$vmclonespec_os.identity.domain=$s_domain#GlobalIPSettings$vmclonespec_os.GlobalIPSettings = New-Object VMware.Vim.CustomizationGlobalIPSettings$vmclonespec_os.GlobalIPSettings.dnsServerList=$s_dns$vmclonespec_os.GlobalIPSettings.dnsSuffixList=$s_domain# adapter mappingfor ( $i=0; $i -lt $nic_cnt; $i++ ) {$vmclonespec_os.NicSettingMap += @(New-Object VMware.Vim.CustomizationAdapterMapping)$vmclonespec_os.NicSettingMap[$i].Adapter = New-Object VMware.Vim.CustomizationIPSettings$vmclonespec_os.NicSettingMap[$i].Adapter = New-Object VMware.Vim.CustomizationIPSettings# FixedIP$vmclonespec_os.NicSettingMap[$i].Adapter.Ip = New-Object VMware.Vim.CustomizationFixedIp$vmclonespec_os.NicSettingMap[$i].Adapter.Ip.IpAddress = $h_network.ip[$i]$vmclonespec_os.NicSettingMap[$i].Adapter.SubnetMask = $h_network.mask[$i]if ( $h_network.gateway[$i] -ne "-" ) {$vmclonespec_os.NicSettingMap[$i].Adapter.Gateway = $h_network.gateway[$i]}}$s_srcname_pre=$s_srcName.substring(0,3)$s_srcname=$s_srcname.Substring( $s_srcname.LastIndexOf(",")+1 )# Template or Virtual Machine from which the guest will be clonedwrite-host "==> Retrieving info for source VM: $s_srcname"if ( $s_srcname_pre -eq "vm," ) {$svm = Get-View (get-vm $s_srcname -ErrorAction stop ).ID}else {$svm = Get-View (get-template $s_srcname -ErrorAction stop ).ID}$tfld = Get-Folder -Name $s_folder -ErrorAction stop | Get-Viewwrite-host "==> Starting clone process ... "$taskid=$svm.CloneVM_Task($tfld.moref,$s_dstname,$vmclonespec_host) | foreach {$_.value}Wait-for-Task "Task-$taskid"write-host "==> Checking new VM ..."get-vm $s_dstname -ErrorAction stopwrite-host "==> Removing existing network adapters ... "$adapter = Get-NetworkAdapter -VM "$s_dstname" -ErrorAction stopif ( $adapter -ne $null ) { Remove-NetworkAdapter -NetworkAdapter $adapter -confirm:$false }write-host "==> Adding " $nic_cnt "new network adapters ... "for ( $i=0; $i -lt $nic_cnt; $i++ ) {if ( $h_network.atype[$i] -ne "-" ) {New-NetworkAdapter -Type $h_network.atype[$i] -NetworkName $h_network.pgroup[$i] -VM $s_dstname -StartConnected -ErrorAction stop}else {New-NetworkAdapter -NetworkName $h_network.pgroup[$i] -VM $s_dstname -StartConnected -ErrorAction stop}}write-host "==> Customizing guest OS ... "$newvm = Get-View (get-vm $s_dstname -ErrorAction stop ).ID$taskid=$newvm.CustomizeVM_Task($vmclonespec_os) | foreach {$_.value}Wait-for-Task "Task-$taskid"write-host "==> Checking new VM ..."sleep 4get-vm $s_dstname -ErrorAction stopif ( $S_poweron -eq "yes" ) { start-vm $s_dstname }
Related Documents:
1. vSphere PowerCLI Quick Start
2. Master-PowerShell
3. VMware vSphere Web Services SDK 4.0 (Supported languages: PowerShell C# JAVA Perl )