VMware Cloud Community
jvignacioproj
Contributor
Contributor

PowerCLI scipt question

Hi,

I've got this script (from vc1 or Site A) to help copy a template, convert to VM, migrate VM to vCenter2 in Site B and convert VM to template  but I now need to do the following:

1. Instead of doing each VM one by one, I want to do all of them at the same time in parralel so it doesnt take so long.

2. Instead of have two separate scripts for linux and windows and 2 different template csv's, have 1 script and manage all but have some smarts to recognise its a linux template or windows template (perhaps in the CSV have template name and OS name). Also the linux and windows templates need to land on different ESXi and datastores in vc2.

thanks for your help.

 

#Variables

$vc1 = 'vc1'

$vc2 = 'vc2'

$credentials = Get-Credential

  

#Connect to vCenters

Connect-VIServer -Server $vc1 -Credential $credentials

Connect-VIServer -Server $vc2 -Credential $credentials

#Import CSV file with template names

$currentTemplates = Import-csv templates.csv

  

foreach($template in $currentTemplates){

 

#Check if all templates exist in vCenter 2. If found, delete template permanently (inventory and files). If not found (error action), go to Catch.

Try{

$checkTemplates = Get-Template -Name $($template.template) -Server $vc2 -ErrorAction Stop

Remove-Template -Template $checkTemplates -Server $vc2 -DeletePermanently -Confirm:$false

Write-Output "Removed template $($template.template) on vCenter $vc2"

}

Catch{

Write-Output "Template $($template.template) not found on vCenter $vc2"

}

#Clone existing templates in vCenter1 to vCenter1 in the same folder with a "-clone" amended to the name.

$newTemplate = "$($template.template)-clone"

 

New-Template -Template $($template.template) -Name $newTemplate -Confirm:$false

Write-Output "Cloned template $($template.template) to $newTemplate on vCenter $vc1"

# Get destination host and datastore

 

$esx2 = Get-VMHost -Name host2 -Server $vc2

$ds2 = Get-Datastore -Name ds2 -Server $vc2

 

Write-Output "Converting template $newTemplate to a VM on vCenter $vc1....."

 

Set-Template -Template $newTemplate -ToVM -Confirm:$false -Server $vc1

#Remove the NIC from VM and migrate to vCenter 2

Write-Output "Migrating VM $newTemplate to vCenter $vc2 on host $esx2 and datastore $ds2..."

$nic = Get-NetworkAdapter -VM $newTemplate

Remove-NetworkAdapter -NetworkAdapter $nic -Confirm:$false

Move-VM -VM $newTemplate -Destination $esx2 -Datastore $ds2 

New-NetworkAdapter -VM $newTemplate -NetworkName "PortGroup Name" -StartConnected -Type Vmxnet3

  

Write-Output "Renaming VM $newTemplate to $($template.template) on vCenter $vc2...."

$newVM = Set-VM -VM $newTemplate -Name $($template.template) -Confirm:$false -Server $vc2

Move-VM -VM $newVM -destination "myfolder" -Server$vc2

Write-Output "Converting VM $newVM to a template on vCenter $vc2....."

Set-VM -VM $newVM -ToTemplate -Confirm:$false -Server $vc2

}

  

Disconnect-VIServer -Server $vc1 -Confirm:$false

Disconnect-VIServer -Server $vc2 -Confirm:$false

0 Kudos
30 Replies
jvignacioproj
Contributor
Contributor

Hi LucD, I’m sure and it worked, however after adding the full path, I don’t get any error messages and it continues to work fine, even through a schedule task.

job done Smiley Happy

thanks for all your help!! Appreciated.

0 Kudos
jvignacioproj
Contributor
Contributor

Hi LucD,

I'm now revisiting this same script but extending it to add another 2 vCenters (for production).

The previous one was for (non-production).

Whats the best way of add 2 new vCenters?

The current script moves all the non-production templates from one vCenter to another.

#Import PowerCLI module

Import-module vmware.vimautomation.core

#Variables

$vc1 = 'vcenter1'

$vc2 = 'vcenter2'

$credfile = 'C:\Users\ACCOUNT\AppData\Roaming\VMware\credstore\vicredentials.xml'

$cred = Get-VICredentialStoreItem -File $credfile -Host $vc2

#Connect to vCenters

Connect-VIServer -Server $vc1

Connect-VIServer -Server $vc2 -User $cred.User -Password $cred.Password

#Import CSV file with template names

$currentTemplates = Import-csv \\SERVER\Templates.csv

foreach($template in $currentTemplates){

   

    #Check if all templates exist in vCenter2. If found, delete template permanently (inventory and files). If not found (error action), go to Catch.

    Try{

        $checkTemplates = Get-Template -Name $($template.template) -Server $vc2 -ErrorAction Stop

        Remove-Template -Template $checkTemplates -Server $vc2 -DeletePermanently -Confirm:$false

        Write-Output "Removed template $($template.template) on vCenter $vc2"

    }

    Catch{

        Write-Output "Template $($template.template) not found on vCenter $vc2"

    }

    # Get destination host and datastore

    $esx2 = Get-VMHost -Name $template.vmhost -Server $vc2

    $ds2 = Get-Datastore -Name $template.datastore -Server $vc2

    #Clone existing templates in vCenter1 to vCenter1 in the same folder with a "-clone" amended to the name.

    $newTemplate = "$($template.template)-clone"

    New-Template -Template $($template.template) -Name $newTemplate -Confirm:$false

    Write-Output "Cloned template $($template.template) to $newTemplate on vCenter $vc1"

    #Convert the cloned template to VM

    Write-Output "Converting template $newTemplate to a VM on vCenter $vc1....."

    Set-Template -Template $newTemplate -ToVM -Confirm:$false -Server $vc1

 

    #Remove the NIC from VM and migrate to vCenter2

    Write-Output "Migrating VM $newTemplate to vCenter $vc2 on host $esx2 and datastore $ds2..."

    $nic = Get-NetworkAdapter -VM $newTemplate

    Remove-NetworkAdapter -NetworkAdapter $nic -Confirm:$false

    #vMotion VM from vc1 to vc2 on specific host and datastore

    Move-VM -VM $newTemplate -Destination $esx2 -Datastore $ds2 -Server $vc1

    #Add NIC with specific port group

    New-NetworkAdapter -VM $newTemplate -NetworkName "vCenter2 port group name" -StartConnected -Type Vmxnet3

    #Rename VM to original name

    Write-Output "Renaming VM $newTemplate to $($template.template) on vCenter $vc2...."

    $newVM = Set-VM -VM $newTemplate -Name $($template.template) -Confirm:$false -Server $vc2

    #Move VM into a specific folder

    Move-VM -VM $newVM -Destination "Templates" -Server $vc2

    #Convert VM to template

    Write-Output "Converting VM $newVM to a template on vCenter $vc2....."

    Set-VM -VM $newVM -ToTemplate -Confirm:$false -Server $vc2

}

#Disconnect from both vc's

Disconnect-VIServer -Server $vc1 -Confirm:$false

Disconnect-VIServer -Server $vc2 -Confirm:$false

0 Kudos
LucD
Leadership
Leadership

Yes, it uses DPAPI, which is a not-so-secure method on Windows platforms.

Which is also the reason why the CredentialStoreItem cmdlets are not supported in PS Core, since these DPAPI are not present in .Net Core.

When in normal use, the encryption requires the same account and station as the one that did the encryption.

But there are some documented methods to retrieve the decrypted data.

For day to day use, I think the method is safe enough.
Is it unbreakable?
No, but if the documented methods for decrypting the data can be used, you have another problem in your environment.


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

0 Kudos
jvignacioproj
Contributor
Contributor

Hi LucD,

thanks for that but dont think you answered my question. I'm after improving the existing script that I copied in.

"I'm now revisiting this same script but extending it to add another 2 vCenters (for production).

The previous one was for (non-production).

Whats the best way of add 2 new vCenters?

The current script moves all the non-production templates from one vCenter to another vCenter DR."

0 Kudos
LucD
Leadership
Leadership

Indeed, I was obviously looking at the wrong part of the thread.

Using multiple vCenters is not a problem, but you should probably indicate somehow, which template goes from which vCenter to which vCenter.
Is that info available in an external file, or is there any way to find out by looking at the template?


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

0 Kudos
jvignacioproj
Contributor
Contributor

Hi LucD,

At the moment, the template is stored externally under "templates.csv".

The info is only for the vCenter non-production DR site and where the template should land.

   

templatevmhostdatastore
templateesxiHostdatastoreName
0 Kudos
LucD
Leadership
Leadership

I don't really understand what you are trying to do here?
Adapt the script, so it can work for multiple environments?


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

0 Kudos
jvignacioproj
Contributor
Contributor

Hi LucD,

yes amend the existing script that I posted so it can include 2 new vCenters.

the current script moves templates from our main site vCenter (non-production) to our DR site VCenter (non-production).

im trying to now include moving templates from our main site VCenter (production) to our DR site vCenter (production).

FYi we have 4 vCenters, ( 2 x main site For prod and non prod and 2 x DR site prod and non prod.

hope this now makes sense.

0 Kudos
LucD
Leadership
Leadership

It does, but why not use the same script and just change the vCenternames?
You could even make the names parameters for the script.

Or are these environments all mixed?
Can a template move from the staging vCenter to any other vCenter?


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

0 Kudos
jvignacioproj
Contributor
Contributor

I have tested changing the names in the same script and it works but I don’t want to be doing this manually or maintaining two separate scripts (for non prod and prod).

aiming to use the same script but either run the copies at the same time or straight after the other copy.

If you recommend just creating a separate script for prod (same script but change variables) then I can do that.

what do you mean by name parameters? Can you show me the example?

0 Kudos
LucD
Leadership
Leadership

You can make your script accept parameters.
In the script, which you store in a .ps1 file, you add a param statement.

param(

   [string]$vCenter1,

   [string]$vCenter2

)


#Variables

$vc1 = $vCenter1

$vc2 = $vCenter2

Now you can call the script, I assume the name of myscript.ps1, with different values for both parameters.

Like this

.\myscript.ps1 -vCenter1 'vc1' -vCenter2 'vc2'

and you change the values on another call of the script

.\myscript.ps1 -vCenter1 'vc3' -vCenter2 'vc4'


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

0 Kudos