Saturday, January 14, 2012

PowerCLI to Create Clones

Got from Steve Poitras

add-pssnapin VMware.VimAutomation.Core

$global:vCenter = "vcenter_ip"
$global:vc_acct = "root"
$global:vc_pass = "password"
$global:location = "Cluster_Name"
$global:datastore = "datastore0"
$global:sourceVMs = @("ubuntu-gold-vmfs-thin", "windows-gold-vmfs-thick")
$global:testIterations = 75


#####################
##### Functions #####
#####################

#Connect VI Server
function connectVIServer {
Connect-VIServer $global:vCenter -User $global:vc_acct -Password $global:vc_pass
}

#Build menu function
function buildMenu ($title,$data) {
$increment = 0
write-host ""
write-host $title
$data | %{
$increment +=1
write-host "$increment." $_
}
$selection = $data[(read-host "Please select an option [Example: 1]")-1]
write-host "You selected: $selection"
return $selection
}

Function Wait-VMGuest
{
<#
.SYNOPSIS
Wait while the VM performs a power operation.
.DESCRIPTION
Wait while the VM performs a power operation. usefull when working with
VMGuests. uses VMware tools to denote a startup, and powerOff.
.PARAMETER VM
VM object to wait on
.PARAMETER VMGuest
VMGuest object to wait on
.PARAMETER Operation
Type of power Operation to wait on valid values are: 'Startup', and 'Shutdown'
.EXAMPLE
Get-VM VM01 | Start-VM | Wait-VM -Operation 'Startup'| Update-Tools
.EXAMPLE
Get-VM VM01 | Shutdown-VMGuest | Wait-VM -Operation 'Shutdown'| Set-vm -NumCpu 2 | start-VM
#>
[cmdletbinding(DefaultParameterSetName='VM')]
Param(
[parameter(Position=0
, ParameterSetName='VM'
)]
[parameter(Position=0
, ParameterSetName='Guest'
)]
[ValidateSet("Startup","Shutdown")]
[string]
$Operation
,
[parameter(Mandatory=$True
, ValueFromPipeline=$True
, HelpMessage='Virtual Machine object to wait on'
, ParameterSetName='VM'
)]
[VMware.VimAutomation.ViCore.Impl.V1.Inventory.VirtualMachineImpl]
$VM
,
[parameter(Mandatory=$True
, ValueFromPipeline=$True
, HelpMessage='The VM Guest object to wait on'
, ParameterSetName='Guest'
)]
[VMware.VimAutomation.ViCore.Impl.V1.VM.Guest.VMGuestImpl]
$VMGuest

)
Process {
IF ($PSCmdlet.ParameterSetName -eq 'Guest') {
$VM = $VMGuest.VM
}
Switch ($Operation)
{
"Startup"
{
while ($vm.ExtensionData.Guest.ToolsRunningStatus -eq "guestToolsNotRunning")
{
Start-Sleep -Seconds 1
$vm.ExtensionData.UpdateViewData("Guest")
}
# return a fresh VMObject
Write-Output (Get-VM $VM)
break;
}
"Shutdown"
{
# wait for the VM to be shutdown
while ($VM.ExtensionData.Runtime.PowerState -ne "poweredOff")
{
Start-Sleep -Seconds 1
$vm.ExtensionData.UpdateViewData("Runtime.PowerState")
}
# return a fresh VMObject
Write-Output (Get-VM $VM)
break;
}
}
}
}



#Clone from VM - Linked Clone
function cloneLinkedVM($sourceVM,$targetDS){

$vmView = $sourceVM | Get-View
$date = Get-Date -Format "yyyMMddhhmmss"

$cloneSpec = new-object Vmware.Vim.VirtualMachineCloneSpec
$cloneSpec.Snapshot = $vmView.Snapshot.CurrentSnapshot
$cloneName = "$sourceVM-clone-$date"
$cloneFolder = $vmView.parent

$dsView = $sourceVM | Get-Datastore | Get-View

$cloneSpec.Location = new-object Vmware.Vim.VirtualMachineRelocateSpec
$cloneSpec.Location.DiskMoveType = [Vmware.Vim.VirtualMachineRelocateDiskMoveOptions]::createNewChildDiskBacking
$cloneSpec.Location.Datastore = $targetDS.Extensiondata.MoRef

write-host "Folder is: $cloneFolder"
write-host "Clone Name is: $CloneName"
write-host "Snapshot is: $cloneSpec.Snapshot"

write-host "Creating linked clone of $sourceVM"
$task = $vmView.CloneVM_Task( $cloneFolder, $cloneName, $cloneSpec )

Start-Sleep -Seconds 10
$cloneVM = Get-VM -Name $cloneName
return $cloneVM
}

#Clone a basic VM
function cloneHotVM($sourceVM,$format) {

$vmView = $sourceVM | Get-View
$date = Get-Date -Format "yyyMMddhhmm"
$activity = "Clone VM - Hot to $format disks"

$cloneSpec = new-object Vmware.Vim.VirtualMachineCloneSpec
$cloneSpec.Snapshot = $vmView.Snapshot.CurrentSnapshot
$cloneName = "$sourceVM-clone-$date"
$cloneFolder = $vmView.parent

$dsView = $sourceVM | Get-Datastore | Get-View

$cloneSpec.Location = New-Object VMware.Vim.VirtualMachineRelocateSpec
$cloneSpec.Location.Datastore = $dsView.MoRef

if($format -match "Thin"){
write-host "Target disk format is Thin"
$cloneSpec.Location.Transform = [Vmware.Vim.VirtualMachineRelocateTransformation]::sparse
}else{
write-host "Target disk format is Thick"
$cloneSpec.Location.Transform = [Vmware.Vim.VirtualMachineRelocateTransformation]::flat
}

write-host "Folder is: $cloneFolder"
write-host "Clone Name is: $CloneName"
write-host "Snapshot is:" $cloneSpec.Snapshot

write-host "Creating clone of $sourcevM"
$task = $vmView.CloneVM_Task( $cloneFolder, $cloneName, $cloneSpec )

findTaskDetails $task $activity
write-host "Task is" $task

#Start new VM
$cloneVM = Get-VM -Name $cloneName
$cloneVM | Start-VM
$cloneView = $cloneVM | Get-View

if($cloneVM){
#VM Exists
#Wait until the clone is started
while($cloneVM.'PowerState' -ne "PoweredOn"){
Start-Sleep -Seconds 10
#$cloneView.ExtensionData.UpdateViewData('Runtime.PowerState')
write-host "$sourceVM state is " $cloneVM.'PowerState' " waiting..."
$cloneVM = Get-VM $cloneVM
}
}

#Cleanup the clone
$cloneVM | Stop-VM -Confirm:$false | Out-null
$cloneVM | Remove-VM -DeletePermanently -Confirm:$false
}

#Clone from VM
function cloneColdVM($sourceVM,$format){

$vmView = $sourceVM | Get-View
$date = Get-Date -Format "yyyMMddhhmm"
$activity = "Clone VM - Cold to $format disks"

if($sourceVM.'PowerState' -eq "PoweredOn") {
if($vmView.guest.toolsstatus -eq "toolsOk"){
#Power off VM
write-host "$sourceVM is powered on, shutting down!"
Shutdown-VMGuest -VM $sourceVM -Confirm:$false | Out-null
}else{
#Hard power off vm
write-host "VMtools not installed performing hard power off"
Stop-VM -VM $sourceVM -Confirm:$false | Out-null
}
}

while ($sourceVM.'PowerState' -ne "PoweredOff") {
Start-Sleep -Seconds 10
#$vmView.ExtensionData.UpdateViewData('Runtime.PowerState')
write-host "$sourceVM state is " $sourceVM.'PowerState' " waiting..."
#Perform hard power off
$sourceVM = Get-VM $sourceVM
$sourceVM | Stop-VM -Confirm:$false
}

#Take Snapshot
write-host "Taking snapshot of $sourceVM"
New-Snapshot -VM $sourceVM -Name "$vm-SNAP$date" | Out-null

$cloneSpec = new-object Vmware.Vim.VirtualMachineCloneSpec
$cloneSpec.Snapshot = $vmView.Snapshot.CurrentSnapshot
$cloneName = "$sourceVM-clone-$date"
$cloneFolder = $vmView.parent

$dsView = $sourceVM | Get-Datastore | Get-View

$cloneSpec.Location = New-Object VMware.Vim.VirtualMachineRelocateSpec
$cloneSpec.Location.Datastore = $dsView.MoRef

if($format -match "Thin"){
write-host "Target disk format is Thin"
$cloneSpec.Location.Transform = [Vmware.Vim.VirtualMachineRelocateTransformation]::sparse
}else{
write-host "Target disk format is Thick"
$cloneSpec.Location.Transform = [Vmware.Vim.VirtualMachineRelocateTransformation]::flat
}

write-host "Folder is: $cloneFolder"
write-host "Clone Name is: $CloneName"
write-host "Snapshot is: $cloneSpec.Snapshot"

write-host "Creating clone of $sourcevM"
$task = $vmView.CloneVM_Task( $cloneFolder, $cloneName, $cloneSpec )

findTaskDetails $task $activity
write-host "Task is" $task

if($sourceVM.'PowerState' -ne "PoweredOn") {
#Start source VM
$sourceVM | Start-VM -RunAsync
}

#Start new VM
$cloneVM = Get-VM -Name $cloneName
$cloneVM | Start-VM
$cloneView = $cloneVM | Get-View

#Wait until the clone is started
if($cloneVM){
#VM Exists
while($cloneVM.'PowerState' -ne "PoweredOn"){
Start-Sleep -Seconds 10
#$cloneView.ExtensionData.UpdateViewData('Runtime.PowerState')
write-host "$sourceVM state is " $cloneVM.'PowerState' " waiting..."
$cloneVM = Get-VM $cloneVM
}
}

#Cleanup the clone
#$cloneVM | Stop-VM -Confirm:$false | Out-null
#$cloneVM | Remove-VM -DeletePermanently -Confirm:$false
}

###END - THIS SECTION MUST BE RUN###

#Connect to VIServer and Perform Tests
connectVIServer

foreach ($sourceVMName in $global:sourceVMs) {

for($i=1; $i -le $global:testIterations; $i++) {
write-host "Provision Linked Clone from $sourceVMName "
$sourceVM = Get-VM -Name $sourceVMName -Location $global:location
if (!$sourceVM) {exit 1}
$cVM = cloneLinkedVM $sourceVM (Get-Datastore -Name $global:datastore)
if (!$cVM) { exit 1}
else {
$cVM | Start-VM
while($cVM.'PowerState' -ne "PoweredOn"){
Start-Sleep -Seconds 10
write-host "$cVM.'name' state is " $cVM.'PowerState' " waiting..."
$cVM = Get-VM $cVM
}

#$cVM | Stop-VM -Confirm:$false
#$cVM | Remove-VM -DeletePermanently -Confirm:$false
}
}
}

#Get-VM -Location $global:location | where {$_.name -match "ubunutu-gold-vmfs-thin-clone-" -And $_.'PowerState' -ne "PoweredOn"} | Remove-VM -DeletePermanently -Confirm:$false

1 comment:

Jerome Joseph said...

Thanks to Steve Poitras