VMware Cloud Community
Scott_G1
Enthusiast
Enthusiast
Jump to solution

Need help with a script

Hey folks. I have been using the script below and it works very well when doing 1 VM. When I try and do multiple VM's it does the template copy first for ALL vm's, and ends up doing customization for only the last one in the list. What I need is to know how to tweak this so that the script builds 1 VM at a time including customization and power on, then goes on to #2, 3 etc.

Thanks to Mark and Lucd for the original script

##########################################################

#

# Mark Jones 2/23/2012

# Version 3

#

##########################################################

Set-PowerCLIConfiguration -InvalidCertificateAction Ignore -Confirm:$false

$vcenter = Read-Host "Enter Vcenter Name"

$csvimport = Read-Host "Enter CSV filename (fullname with extension)"

$username = read-host "Enter your domain admin username for customization"

$pass = Read-Host -AsSecureString "Enter your password"

$adminpass = Read-Host -AsSecureString "Enter local admin password"

#convert back to string

$pass = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($pass)

$pass = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($pass)

$adminpass = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($adminpass)

$adminpass = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($adminpass)

Connect-VIServer $vcenter

$vmlist = Import-CSV $csvimport

foreach ($item in $vmlist) {

    # I like to map out my variables

    $basevm = $item.template

    $datastore = $item.datastore

    $vmhost = $item.vmhost

    $custspec = $item.custspec

    $vmname = $item.vmname

    $ipaddr = $item.ipaddress

    $subnet = $item.subnet

    $gateway = $item.gateway

    $pdns = $item.pdns

    $sdns = $item.sdns

    $vlan = $item.vlan

    $location = $item.location    

  

    #Clone the templates

    $tasks += (New-VM -Name $vmname -template $basevm -Location $location -Datastore $datastore -VMHost $vmhost -RunAsync)

}

Write-Host "Waiting for Copies to Finish"

#Wait for all taksks in tasks list before proceeding

Wait-Task -task $tasks

foreach ($item in $vmlist) {

    $datastore = $item.datastore

    $custspec = $item.custspec

    $ipaddr = $item.ipaddress

    $subnet = $item.subnet

    $gateway = $item.gateway

    $pdns = $item.pdns

    $sdns = $item.sdns

#   $vlan = $item.vlan

    $hd = [int]$item.ddrive * 1024 * 1024

    $hd2 = [int]$item.edrive * 1024 * 1024

    $hd3 = [int]$item.fdrive * 1024 * 1024

    $vmname = $item.vmname

    $cpu = $item.cpu

    $mem = [int]$item.mem * 1024

  #set customization spec

  New-OSCustomizationSpec -spec $custspec -Name $vmname -type Persistent

  Set-OSCustomizationSpec -spec $vmname -AdminPassword $adminpass -DomainUsername $username -DomainPassword $pass -Confirm:$false

  Get-OSCustomizationSpec $vmname | Get-OSCustomizationNicMapping | Set-OSCustomizationNicMapping -IpMode UseStaticIp -IpAddress $ipaddr -SubnetMask $subnet -DefaultGateway $gateway -Dns $pdns,$sdns

    

    #Set network label

#   Get-VM -Name $vmname | Get-NetworkAdapter | Set-NetworkAdapter -NetworkName $vlan -Confirm:$false | Out-Null

    #set vm

    Set-VM -VM $vmname -OSCustomizationSpec $vmname -NumCpu $cpu -MemoryMB $mem -Confirm:$false

    #Create D drive windows

    if ($hd){

    New-HardDisk -VM $vmname -CapacityKB $hd -ThinProvisioned:$true -Confirm:$false

    }

    #Create E drive windows

    if ($hd2){

    New-HardDisk -VM $vmname -CapacityKB $hd2 -Confirm:$false

    }

    #Create F drive windows

    if ($hd3){

    New-HardDisk -VM $vmname -CapacityKB $hd3 -Confirm:$false

    }

    #Remove Cust Spec

    Remove-OSCustomizationSpec -CustomizationSpec $vmname -Confirm:$false

  

}

foreach ($item in $vmlist){

$vmname = $item.vmname

#Start VM

    Start-VM -VM $vmname -Confirm:$false -RunAsync

}

Disconnect-VIServer $vcenter -Confirm:$false

Reply
0 Kudos
1 Solution

Accepted Solutions
LucD
Leadership
Leadership
Jump to solution

Try replacing this

$tasks += (New-VM -Name $vmname -template $basevm -Location $location -Datastore $datastore -VMHost $vmhost -RunAsync)

with

$tasks = @(New-VM -Name $vmname -template $basevm -Location $location -Datastore $datastore -VMHost $vmhost -RunAsync)

The error came from the fact that there is now only 1 task generated by the New-VM, and the variable $tasks we not defined as an array in the script.

You can use the addition on an array, but not on a simple variable.

With the @(...) construct, we turn the single object into an array with 1 element.


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

View solution in original post

Reply
0 Kudos
3 Replies
LucD
Leadership
Leadership
Jump to solution

Change the 2 ForEach loops into 1 ForEach loop.

Remove the indicated lines.

loop.jpg

You could also drop a number of the assignments in the beginning of the 2nd loop, since you already have those variables populated at the beginning of the 1st loop


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

Scott_G1
Enthusiast
Enthusiast
Jump to solution

Hey Lucd,

I made those changes and it went through and made all the provisioning for the first VM then spit out this error

Method invocation failed because [VMware.VimAutomation.ViCore.Impl.V1.Task.TaskImpl] doesn't contain a method named 'op_Addition'.

At Q:\Scripts\Build\build2.ps1:42 char:14

+     $tasks += <<<<  (New-VM -Name $vmname -template $basevm -Location $location -Datastore $datastore -VMHost $vmhost -RunAsync)

    + CategoryInfo          : InvalidOperation: (op_Addition:String) [], RuntimeException

    + FullyQualifiedErrorId : MethodNotFound

After that it did not power on the VM and went to start on VM2.

To add to this, is there a way to move the newly created VM's to a folder?

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

Try replacing this

$tasks += (New-VM -Name $vmname -template $basevm -Location $location -Datastore $datastore -VMHost $vmhost -RunAsync)

with

$tasks = @(New-VM -Name $vmname -template $basevm -Location $location -Datastore $datastore -VMHost $vmhost -RunAsync)

The error came from the fact that there is now only 1 task generated by the New-VM, and the variable $tasks we not defined as an array in the script.

You can use the addition on an array, but not on a simple variable.

With the @(...) construct, we turn the single object into an array with 1 element.


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

Reply
0 Kudos