Create a linked clone from a parent vm using vmware sdk

I was working on a project to create a 90 day eval machine that used linked clones.  This article isn’t meant to educate on Linked clones although it’s a great concept to have a Parent VM and another disk that contains just changes.  The benefits saves a lot of space in storage.   

Text only version of script

Here is a couple articles to check on linked clones

Here is the script

    [string]$ParentVMName = “UP1”,
    [string]$vCenterHostName = “vCenterSS”,
    [string]$vCenterUserName= “domainuser”,
    [string]$vCenterUserPassword= “UP2”,
    [string]$cloneName = “UP3”,
    [string]$OSType = “Windows”,
    [string]$TimeZone = “035”,
    [string]$DHCPPortGroup = “123456”,
    [string]$Domain = “”,
    [string]$DomainUserName = “”,
    [string]$DomainPassword = “UP4”,
    [string]$AdminPassword = “changeme”,
    [string]$FullName = “CompanyA”,
    [string]$OrgName = “Example, Inc”,
    [string]$CustomizeTemplate1 = “$($cloneName)-Temp1”,
    [string]$CustomizeTemplate2 = “$($cloneName)-Temp2”,
    [string]$ServerDescription = “UP5”,
    [string]$PrimaryDNSSuffix = “”,
    #This is a enum VM, PREFIX CUSTOM

function LoadSnapin{
  if (!(Get-PSSnapin | where {$_.Name -eq $PSSnapinName})){
    Add-pssnapin -name $PSSnapinName
LoadSnapin -PSSnapinName   “VMware.VimAutomation.Core”

#Better to pass in an array and randomly select datastore
function GetDataStore
    $value = (Get-Random) %3
    switch ($value)
        0 {    return “datastore1”    }
        1 {    return “datastore2”    }
        2 {    return “datastore3”    }
        default {return “datastore1”}

# Constants for status
$STATUS_STARTED = “CustomizationStarted”
$STATUS_SUCCEEDED = “CustomizationSucceeded”
$STATUS_FAILED = “CustomizationFailed”
# constants for event types     
$EVENT_TYPE_CUSTOMIZATION_STARTED = “VMware.Vim.CustomizationStartedEvent”
$EVENT_TYPE_CUSTOMIZATION_SUCCEEDED = “VMware.Vim.CustomizationSucceeded”
$EVENT_TYPE_CUSTOMIZATION_FAILED = “VMware.Vim.CustomizationFailed”
$EVENT_TYPE_VM_START = “VMware.Vim.VmStartingEvent”
# seconds to sleep before next loop iteration
[int] $timeoutSeconds = 1200

function GetOSCustomizationSpecStatus($vm, $timeoutSeconds)
   # the moment in which the script has started
   # the maximum time to wait is measured from this moment
   $startTime = Get-Date
   # we will check for “start vm” events 5 minutes before current moment
   $startTimeEventFilter = $startTime.AddMinutes(-5)
   # initializing list of helper objects
   # each object holds VM, customization status and the last VmStarting event
   $vmDescriptors = New-Object System.Collections.ArrayList

   Write-Host “Start monitoring customization process for vm ‘$vm'”
   $obj = “” | select VM,CustomizationStatus,StartVMEvent
   $obj.VM = $vm
   # getting all events for the $vm,
   #  filter them by type,
   #  sort them by CreatedTime,
   #  get the last one
   $obj.StartVMEvent = Get-VIEvent -Entity $vm -Start $startTimeEventFilter | where { $_ -is $EVENT_TYPE_VM_START } | Sort CreatedTime | Select -Last 1
    if (-not $obj.StartVMEvent)
        $obj.CustomizationStatus = $STATUS_VM_NOT_STARTED
    } else
        $obj.CustomizationStatus = $STATUS_CUSTOMIZATION_NOT_STARTED
   # declaring script block which will evaluate whether
   # to continue waiting for customization status update
   $shouldContinue = {
      # is there more virtual machines to wait for customization status update
      # we should wait for VMs with status $STATUS_STARTED or $STATUS_CUSTOMIZATION_NOT_STARTED
      $notCompletedVms = $vmDescriptors | where { $STATUS_NOT_COMPLETED_LIST -contains $_.CustomizationStatus }
      # evaluating the time that has elapsed since the script is running
      $currentTime = Get-Date
      $timeElapsed = $currentTime – $startTime
      $timoutNotElapsed = ($timeElapsed.TotalSeconds -lt $timeoutSeconds)
      # returns $true if there are more virtual machines to monitor
      # and the timeout is not elapsed
      return ( ($notCompletedVms -ne $null) -and ($timoutNotElapsed) )
   while (& $shouldContinue)
      foreach ($vmItem in $vmDescriptors)
         $vmName = $vmItem.VM.Name
         switch ($vmItem.CustomizationStatus)
               # we should check for customization started event
               $vmEvents = Get-VIEvent -Entity $vmItem.VM -Start $vmItem.StartVMEvent.CreatedTime
               $startEvent = $vmEvents | where { $_ -is $EVENT_TYPE_CUSTOMIZATION_STARTED }
               if ($startEvent) {
                  $vmItem.CustomizationStatus = $STATUS_STARTED
                  Write-Host “Customization for VM ‘$($vm)’ has started”
               # we should check for customization succeeded or failed event
               $vmEvents = Get-VIEvent -Entity $vmItem.VM -Start $vmItem.StartVMEvent.CreatedTime
               $succeedEvent = $vmEvents | where { $_ -is $EVENT_TYPE_CUSTOMIZATION_SUCCEEDED }
               $failedEvent = $vmEvents | where { $_ -is $EVENT_TYPE_CUSTOMIZATION_FAILED }
               if ($succeedEvent)
                  $vmItem.CustomizationStatus = $STATUS_SUCCEEDED
                  Write-Host “Customization for VM ‘$($vm)’ has successfully completed”
               if ($failedEvent)
                  $vmItem.CustomizationStatus = $STATUS_FAILED
                  Write-Host “Customization for VM ‘$($vm)’ has failed”
               # in all other cases there is nothing to do
               #    $STATUS_VM_NOT_STARTED -> if VM is not started, there’s no point to look for customization events
               #    $STATUS_SUCCEEDED -> customization is already succeeded
               #    $STATUS_FAILED -> customization
         } # end of switch
      } # end of the foreach loop
      Write-Host “Sleeping for $WAIT_INTERVAL_SECONDS seconds”
   } # end of while loop
   # preparing result, without the helper column StartVMEvent
   $result = $vmDescriptors | select VM,CustomizationStatus
   Write-Host “I’m here $result[1]”

   if($result[1] -ne “CustomizationSucceeded”)
    write-host “Waiting for VM Tools to Start”
    do {

    $toolsStatus = (Get-VM $cloneName).extensiondata.Guest.ToolsStatus

    write-host $toolsStatus

    start-sleep -s 5

    } until ( $toolsStatus -eq ‘toolsOk’ )
    Write-Host “Tools are running”

    $InvokeAdminPassword = ConvertTo-SecureString -String $AdminPassword -asplaintext -force
    $cmdAddToDomain = “netdom join /d:$($Domain) $cloneName /ud:$($DomainUserName) /pd:$($DomainPassword) /reboot:30”
    If ($ParentVMName -match ‘DEV1’ )
            $varAddToDomain = Invoke-VMScript -VM $cloneName -ScriptText $cmdAddToDomain -GuestUser “DevAdmin1” -GuestPassword $InvokeAdminPassword
            $varAddToDomain = Invoke-VMScript -VM $cloneName -ScriptText $cmdAddToDomain -GuestUser “Admin1” -GuestPassword $InvokeAdminPassword
    $varAddToDomain = Invoke-VMScript -VM $cloneName -ScriptText $cmdAddToDomain -GuestUser “Admin1” -GuestPassword $InvokeAdminPassword
    Write-Host $varAddToDomain
   return $result

function AddToDomain
    write-host “Waiting for VM Tools to Start”

<#    do {

    $toolsStatus = (Get-VM $cloneName).extensiondata.Guest.ToolsStatus

    write-host $toolsStatus

    start-sleep -s 5

    } until ( $toolsStatus -eq ‘toolsOk’ )
    Write-Host “Tools are running”

    Write-Host “Add to Domain using Netdom”
    $InvokeAdminPassword = ConvertTo-SecureString -String $AdminPassword -asplaintext -force
    $cmd = “netdom join /d:$($Domain) $cloneName /ud:$($DomainUserName) /pd:$($DomainPassword) /reboot:30”
        If ($ParentVMName -match ‘Dev1’ )
            $netDomOutPut = Invoke-VMScript -VM $cloneName -ScriptText $cmd -GuestUser “DevAdmin1” -GuestPassword $InvokeAdminPassword
            $netDomOutPut = Invoke-VMScript -VM $cloneName -ScriptText $cmd -GuestUser “Admin1” -GuestPassword $InvokeAdminPassword
    $netDomOutPut = Invoke-VMScript -VM $cloneName -ScriptText $cmd -GuestUser “Admin1” -GuestPassword $InvokeAdminPassword
    $date = Get-Date -Format MM-dd-yy

    #Adding output of netdom for Scorch to consume
    Add-Content -path “F:LogsNetDomOutput$($cloneName)-$($date).txt” -value $netDomOutPut -force
    ipconfig /registerdns

Connect-VIServer -Server $vCenterHostName -User $vCenterUserName -Password $vCenterUserPassword

    #Creates the VM
    $sourceVM = Get-VM $ParentVMName | Get-View
    $cloneFolder = $sourceVM.parent
    $cloneSpec = new-object Vmware.Vim.VirtualMachineCloneSpec
    $cloneSpec.Snapshot = $sourceVM.Snapshot.CurrentSnapshot
    $cloneSpec.Location = new-object Vmware.Vim.VirtualMachineRelocateSpec

    #Creates Linked clone
    $cloneSpec.Location.DiskMoveType = [Vmware.Vim.VirtualMachineRelocateDiskMoveOptions]::createNewChildDiskBacking

    #Defines the Datastore, calls a function to get a specific datastore
    $Datastore = GetDataStore
    $cloneSpec.Location.Datastore = (Get-View -ViewType Datastore -Property Name -Filter @{“Name”=$DataStore}).MoRef
    $sourceVM.CloneVM_Task( $cloneFolder, $cloneName, $cloneSpec )

    $Spec1 = New-OSCustomizationSpec -FullName $FullName -OrgName $OrgName -OSType $OSType -ChangeSID -Name $CustomizeTemplate1 -Type NonPersistent -WorkGroup WK -AdminPassword $AdminPassword -TimeZone $TimeZone -Description $ServerDescription -LicenseMode PerSeat -DnsSuffix $PrimaryDNSSuffix
    Start-Sleep -s 4
    $Spec1 = Get-OSCustomizationSpec $CustomizeTemplate1
    Start-Sleep -s 4

    Get-VM $cloneName | Set-VM -OSCustomizationSpec $Spec1 -Confirm:$false -Description $ServerDescription | Start-VM
    $NIC = Get-NetworkAdapter -VM $cloneName
    Set-NetworkAdapter -NetworkAdapter $NIC -Connected $false -StartConnected $false -Confirm:$false
    Start-Sleep -s 4

    GetOSCustomizationSpecStatus -Vm $cloneName -timeoutSeconds 1200

    $a = Get-VM -Name $cloneName
    Stop-VM -VM $a -confirm:0

    Start-Sleep -m 250

    while ($a.PowerState -eq “PoweredOn”)
        Write-Host “Sleeping for 5 seconds”
        $a = get-vm -Name $cloneName
        start-sleep -s 5

    Get-VM $cloneName  | Start-VM
    Start-Sleep 30
    $NIC = Get-NetworkAdapter -VM $cloneName
    Set-NetworkAdapter -NetworkAdapter $NIC -NetworkName $DHCPPortGroup -Connected $true -StartConnected $true -Confirm:$false
    Start-Sleep 30

    #GetOSCustomizationSpecStatus -Vm $cloneName -timeoutSeconds 1200
    Remove-OSCustomizationSpec -OSCustomizationSpec $Spec1 -Confirm:$false

Disconnect-VIServer -Server $vCenterHostName -Confirm:$false | out-null

process files with .TMP file extensions

We received a question how to process with .TMP file extensions.  IISLogs has a feature called Per Directory that was introduced in 2.0.  The feature allows an administrator to have granular control on a per directory basis.  We added the .TMP extension as an option in the Per Directory feature, please review the Per Directory article for complete options.  If you have any questions, feel free to contact our support alias @

Open IISLogsGUI, Select Per Directory option

Fill in the Directory Name and other attributes you need.

Select TMP


When you save this, in the install folder the data is stored in a file called IISLogsPerDirectory.xml

<?xml version=”1.0″ standalone=”yes”?>


Steve Schofield
Microsoft MVP – IIS

Pondering Thought: Significant


Job 38

There are many insignificant things in the world
Not many people are concerned about our worries

Some will genuinely be concerned
Over time, less people will be worry about you

Good thing family will always be there
Through thick and thin

No matter the circumstances
No matter the obstacle

Besides God
Family is the most significant thing in life

The enemy has been trying since the dawn of time
To break down the family and cause distractions

When comparing ourselves to God
We are insignificant

We can’t command oceans
We can’t command the dew in the morning

We can’t control the sun from rising
Nor can we do much of anything alone

Don’t focus on insignificant things
We are human, we will sin

Sin is significant in God’s eyes
It makes him sad

All sin is the same to Him
No one sin is greater than another

We can attempt things, we might succeed for awhile
This is only temporary

When we seek God in all things
He is there, waiting to show his love, grace and mercy

We are forgiven when we accept his Son’s free gift of external life
We get to spend eternity in His house

That is the most significant thing that’ll ever happen
Just endure while on earth

We are significant in Gods eyes
In the end, being Gods child is all that really matters


Story Behind the Poem

This word was derived from a ‘pondering thought’ I published on Face book; Here is the saying;. “In the world today, there are so many insignificant things and many view themselves as such, in God’s eyes you are significant, shown by his love, grace and mercy!”

The previous day I had a self-indulged ‘self-pity party’ all day worrying about not being able to have a medical procedure performed immediately, I had to wait due to cost. God reminded me clearly I’m significant in his eyes and the next day was awesome. I was blaming just about everyone who thought differently than me. I knew scripture was correct and I was wrong, I was just being selfish. God word is is powerful medicine!

Continuing on with Daniel’s plan

Its been a few days and still on the prowl of losing weight, learning how to eat differently.  My wife has been awesome putting together some tasty meals.  One of the options to exclude from the diet is wheat (Ive later learned Glutton).  I dont know all the details, many things use this ingredient.  Although Ive not followed the diet to the letter, my eating habits have improved greatly.  during the day, Ive been snacking on oranges, broccoli, cauliflower and apples.  It helps with the mid-morning and mid-afternoon urges to snack.  My downfall is after I get home from work, all I want to do is snack.  Chips, cookies, leftovers or whatever is laying around.  The vegies and fruit has helped. 

Im down around 4.1 pounds in seven days.  My goal is initially 6 8 pounds, then well see how my body reacts.   If I had to wish, Id like 18 as a phase 1.  I suppose when you reach one goal, youll keep going.  I hope to reach this crossroads in the future, for now, my faith is strong.  God is actively in the project and Im leaning on Him for strength to succeed

Praise God,


Daniel diet notes day 1 and 2

Day 1 and 2 notes.  I weighed myself and my goal is 8.5 pounds to shed. Anything more is frosting on the cake, even though we cant have it. 🙂 My wife and I are attempting the Daniel Plan written by Rick Warren and some other authors, Rick is the head pastor from Saddleback church.   Its a 10 day detox and 30 day diet helping change the way a person eats.   For me, i dont drink anything on a regular basis with caffeine, which my wife has a slight obsession with Diet Coke, and Chocolate.  I like sweets though!

When we were shopping for the food, there is nothing cheap about ingredients to make the food.  This will be my first adventure into a diet per se.  Im glad cause my wife does the cooking, previous attempts to watch what I eat, generally failed.  Im stuck at a certain weight even though I work out 3 to 4 days a week.  I did a sprint triathlon in 2012 and worked out 5 and 6 days a week.  Even this didnt help lose a lot of weight.  This proved a diet is critical part of toning up and losing weight. 

We were shopping, one funny thing I realized, Im glad we dont have to diet toliet paper.  Everything else we purchased was new!  The first day consisted of salad, vegies, a new vinegar based salad dressing.  We had stir fry with some tofu (fake meat), which wasnt too bad either.  

On the faith side, the wife and are using the Duck Dynasty devotional book my wife got for me Christmas.  Unlike other attempts, this is my first adventure actively including my faith.  If its in His will, we will succeed.  I believe that 100%.

The word that came out of our devotionals, perseverance –

steadfastness in doing something despite difficulty or delay in achieving success

Lord, I pray for help with the change in diet, change in habits and be present for my wife and I during this journey.


Stay tuned,