Skip to content

Instantly share code, notes, and snippets.

@coza73
Last active December 10, 2020 17:27
Show Gist options
  • Save coza73/890a665ec60e49c365aaec9b16f380fe to your computer and use it in GitHub Desktop.
Save coza73/890a665ec60e49c365aaec9b16f380fe to your computer and use it in GitHub Desktop.
Get-Module –ListAvailable VM* | Import-Module -ErrorAction SilentlyContinue
Set-PowerCLIConfiguration -DefaultVIServerMode Multiple -Confirm:$false
# Make sure no vcenters are connected that dont need to be.
if ($global:DefaultVIServer.IsConnected -eq $true){
write-host "We have vcenters still connected, disconnecting....." -ForegroundColor Red
Disconnect-VIServer * -Confirm:$false
}
function log ([string]$logdata){
$logfile = "c:\temp\MigrateTemplate.log"
$date = get-date
Write-Output "$date - $logdata" | Out-File $logfile -width 240 -Append
}
Log "Starting"
# check first if ovf tool is installed if not exit
$ovftoolpaths = ("C:\Program Files (x86)\VMware\VMware OVF Tool\ovftool.exe", "C:\Program Files\VMware\VMware OVF Tool\ovftool.exe")
$ovftool = ""
foreach ($ovftoolpath in $ovftoolpaths)
{
if(test-path $ovftoolpath)
{
$ovftool = $ovftoolpath
}
}
if (!$ovftool)
{
write-host -ForegroundColor red "ERROR: OVFtool not found in it"s standard path."
Log "ERROR: OVFtool not found in it"s standard path."
write-host -ForegroundColor red "Edit the path variable or download ovftool here: http://www.vmware.com/support/..."
exit
}
# Make sure you can connect to multiple vCenters in this session
if ((Get-PowerCLIConfiguration -Scope session).defaultviserverMode -ne "Multiple"){
Set-PowerCLIConfiguration -DefaultVIServerMode Multiple -Scope session -WebOperationTimeoutSeconds -1 -Confirm:$false
}
#Set credentials. Now nessessary for connecting to Vsphere Appliance virtualcenter
$credentialFile = "C:\temp\esxranger_cred.txt"
If (Test-Path $credentialFile){
Write-Host "Credential file $credentialFile exists will not ask for password"
}
Else {
log "No credential file found"
read-host -Prompt "ESXRanger nexus password" -assecurestring | convertfrom-securestring | out-file $credentialFile
}
$password = get-content $credentialFile | convertto-securestring
$credential = new-object -typename System.Management.Automation.PSCredential -argumentlist "esxranger",$password
function Copy-Templates {
param
(
[parameter(Mandatory = $true)][String] $SourceViServer,
[parameter(Mandatory = $true)][String] $DestinationViServer,
[parameter(Mandatory = $true)][String] $DestinationDataStore,
[parameter(Mandatory = $true)][String] $SourceDataCenter,
[parameter(Mandatory = $true)][String] $DestinationDataCenter,
[parameter(Mandatory = $true)][String] $DestinationCluster,
[parameter(Mandatory = $true)][String] $DestinationNetworkName,
[parameter(Mandatory = $true)][String] $SourceFolderName,
[parameter(Mandatory = $true)][String] $DestinationFolderName,
[parameter(Mandatory = $false)][String] $appendName, # Append this to destination template name, will also create subfolder under DestinationFolderName
[parameter(Mandatory = $false)][Switch] $force, # Force copy of templates
[parameter(Mandatory = $false)][Switch] $cleanold, #delete templates in old folder that are older than 1 month
[parameter(Mandatory = $false)][Switch] $setTemplateChangeDateFile # do no copying just set a change date file
)
write-host ""
write-host "Migrate to.. "
log "Migrate to.. "
write-host ""
write-host "vCenter: $DestinationViServer"
log "vCenter: $DestinationViServer"
write-host "Datacenter: $DestinationDataCenter"
log "Datacenter: $DestinationDataCenter"
write-host "Cluster: $DestinationCluster"
log "Cluster: $DestinationCluster"
write-host "Folder: $DestinationFolderName"
log "Folder: $DestinationFolderName"
if ($appendName){
write-host "Append Name: $appendName"
log "Append Name: $appendName"
}
if ($force) {
write-host "Forced Migrate" -ForegroundColor Red
log "Forced Migrate"
}
if ($cleanold){
write-host "Clean out old templates" -ForegroundColor Red
log "Clean out old templates"
}
if ($setTemplateChangeDateFile) {
write-host "Only create/overwrite changedate file" -foregroundcolor Magenta
}
write-host ""
write-host "Connecting to Source vCenter" -ForegroundColor Green
connect-viserver $SourceViServer -Credential $credential
write-host "Connecting to Destination vCenter" -ForegroundColor Green
connect-viserver $DestinationViServer -Credential $credential
$vmhost = Get-Cluster $DestinationCluster | Get-VMHost
$DestinationHost = $vmhost[0]
write-host "Creating list of Templates -->" -foregroundcolor blue
$templatesObject = get-Datacenter -Server $SourceViServer -Name $SourceDataCenter | get-folder -Server $SourceViServer -Name $SourceFolderName| get-template -NoRecursion
write-host "Reading from List of Templates -->" -foregroundcolor blue
#grab all the names of the templates in the source folder
foreach ($template in $templatesObject.name) {
#Just making sure we are connected to source VC also need to refresh the session to make sure the session ticket is valid.
if ($DefaultVIServer.name -ne $SourceViServer) {
connect-viserver $SourceViServer -Credential $credential
}
Write-Host "Checking if we need to copy $template"
#Create a Auth ticket for ovftool to connect to host with.
$destinationSession = Get-View -Server $DestinationViServer -Id SessionManager
$destinationTicket = $destinationSession.AcquireCloneTicket()
$sourceSession = Get-View -Id SessionManager -Server $SourceViServer
$SourceTicket = $SourceSession.AcquireCloneTicket()
$templateTempName = $template + "-new"
# Set name of destination template and folder name based whether appendName has been set
if ($appendName) {
$destinationTemplateName = $template + $appendName
$destinationAppendFolderName = $appendName.trim("-")
}
else {
$destinationTemplateName = $template
}
# Create destination folder for appendname if does not exist
if ($appendName) {
if (!(Get-Datacenter -Server $DestinationViServer $destinationDataCenter |get-folder $DestinationFolderName | get-folder $destinationAppendFolderName -NoRecursion -ErrorAction:SilentlyContinue)) {
new-folder -location (Get-Datacenter -Server $DestinationViServer $destinationDataCenter |get-folder $DestinationFolderName) -name $destinationAppendFolderName
}
$destinationFolderObject = Get-Datacenter -Server $DestinationViServer $destinationDataCenter |get-folder $DestinationFolderName | get-folder $destinationAppendFolderName -NoRecursion
}
else {
if (!(Get-Datacenter -Server $DestinationViServer $destinationDataCenter |get-folder $DestinationFolderName -ErrorAction:SilentlyContinue)) {
new-folder -location (Get-Datacenter $destinationDataCenter | get-folder -type VM -norecursion) -name $destinationFolderName
}
$destinationFolderObject = Get-Datacenter -Server $DestinationViServer $destinationDataCenter |get-folder $DestinationFolderName
}
#Get the last changed date from source template object
$templateObject = get-template -Server $SourceViServer -location (Get-Datacenter -Server $SourceViServer -Name $SourceDataCenter | get-folder -Server $SourceViServer -Name $SourceFolderName) $template
$templateObjectChangeDate = (Get-View $templateObject).Config.ChangeVersion
$templateChangeDateFile = "e:\templates\" + $DestinationViServer + " - " + $DestinationDataCenter + " - " + $destinationFolderObject.Name + " - " + $destinationTemplateName + ".txt"
#Get the date changed file for the template, if it does not exist create one
if (Test-Path $templateChangeDateFile) {
$templateChangeDate = Get-Content $templateChangeDateFile
Write-Host "Source template last updated $templateChangeDate" #-ForegroundColor Blue
}
else {
Write-Host "No Change Date file for $template" -ForegroundColor Red
Set-Content $templateChangeDateFile $Null
}
# if -force set to $true then set template date change to $null to force copy
if ($force) {
$templateChangeDate = $Null
}
#if setTemplateChangeDateFile switch set only write a new change date file do no copying
if ($setTemplateChangeDateFile){
write-host "Setting change date file for $template"
Set-Content $templateChangeDateFile $templateObjectChangeDate
}
# If template date changed matches the change date in the file and template exists in the destination
# dont copy else start the copy process
elseif (($templateChangeDate -eq $templateObjectChangeDate) -and (Get-Template -Server $DestinationViServer -Location (Get-Datacenter -Server $DestinationViServer -Name $destinationDataCenter) -Name $destinationTemplateName -ErrorAction:SilentlyContinue)) {
Write-Host "Not copying $template" -ForegroundColor Green
$destinationTemplate = Get-Template -Server $DestinationViServer -Location (Get-Datacenter -Server $DestinationViServer -Name $destinationDataCenter) -Name $destinationTemplateName
$destinationTemplateFolderObject = get-folder -Id $destinationTemplate.ExtensionData.parent
if ($destinationTemplateFolderObject.Id -ne $destinationFolderObject.Id) {
Write-host "$destinationTemplate not in correct folder, moving to $($destinationFolderObject.name) folder" -ForegroundColor Magenta
Move-Template -Server $DestinationViServer -Template $destinationTemplate -destination $destinationFolderObject
}
}
else {
log "Copying $template to vCenter $DestinationViServer $DestinationDataCenter on Cluster $DestinationCluster as $destinationTemplateName"
#Get the Template Moref value to feed into ovftool source
$vmd = $($templateObject.name)
$moref = $templateObject.extensiondata.moref.value
#run ovftool with information collected
$ovfArgList = @(
"--allowExtraConfig"
"--noSSLVerify"
"--diskMode=thin"
"--name=$($templateTempName)"
"-ds=$DestinationDataStore"
"--network=$DestinationNetworkName"
"--I:targetSessionTicket=$destinationTicket"
"--I:sourceSessionTicket=$($sourceTicket)"
"vi://$($DefaultVIServer.name)?moref=vim.VirtualMachine:$($moref)"
"vi://$($DestinationViServer)/$($DestinationDataCenter)?dns=$DestinationHost"
)
#
& $ovftool $ovfArgList
#Test that template actually successfully copied
if (!(get-vm -Server $DestinationViServer -Name $templateTempName)) {
log "$template failed to copy to $DestinationCluster"
Write-Host "$template failed to copy to $DestinationCluster" -ForegroundColor Red
}
#If copy good replace old with new
else {
#Move and rename the old matching template from Destination if exists
if (!(Get-Template -Server $DestinationViServer -location (get-datacenter $destinationDataCenter) -name $destinationTemplateName -ErrorAction:SilentlyContinue)) {
log "Old Destination template does not exist --> $destinationTemplateName"
Write-Host "Old Destination template does not exist --> ""$destinationTemplateName" -ForegroundColor Magenta
}
Else {
log "Moving old template --> $destinationTemplateName"
write-host "Moving old template --> " "$destinationTemplateName" -ForegroundColor Blue
#check for 'old' folder if not there created one
if (!(Get-Datacenter -Server $DestinationViServer $destinationDataCenter |get-folder $DestinationFolderName | get-folder -NoRecursion old -ErrorAction:SilentlyContinue)) {
new-folder -location (Get-Datacenter -Server $DestinationViServer $destinationDataCenter |get-folder $DestinationFolderName ) -name old
}
$oldTemplateObject = Get-Template -Server $DestinationViServer -Location $destinationDataCenter -Name $destinationTemplateName
$oldFolderObject = Get-Datacenter -Server $DestinationViServer $destinationDataCenter |get-folder $DestinationFolderName | get-folder -NoRecursion old
move-template -template $oldTemplateObject -Destination $oldFolderObject
# Rename template to -old-*date*
set-template -template (Get-Template -Server $DestinationViServer -location (get-datacenter $destinationDataCenter) -name $destinationTemplateName) -Name ($destinationTemplateName + "-old-" + (get-date -format "yyyMMdd")) -confirm:$false
}
#Convert imported VM to template and move to configured folder and rename from temp name
log "Converting VM to Template --> $template"
write-host "Converting VM to Template --> " $template -foregroundcolor blue
set-vm -vm (get-vm -server $DestinationViServer -Location $destinationDataCenter $templateTempName) -ToTemplate -name $destinationTemplateName -confirm:$false
$destinationTemplateFolder = Get-Folder -server $DestinationViServer -id (Get-Template -Server $DestinationViServer $destinationTemplateName).FolderID
if ($destinationTemplateFolder -ne $destinationFolderObject) {
log "Moving template to $DestinationFolderName"
Write-Host "Moving template to $DestinationFolderName" -ForegroundColor Blue
Move-Template -Server $DestinationViServer -Template $destinationTemplateName -destination $destinationFolderObject
}
#Update the templates date changed file
Set-Content $templateChangeDateFile $templateObjectChangeDate
}
}
}
# exit here if setTemplateChangeDateFile set
if ($setTemplateChangeDateFile){
Break
}
# Cleanup old and redundant templates
write-host "Checking for redundant templates"
$DestinationTemplatesObject = get-folder -id $destinationFolderObject.id | get-template -NoRecursion
foreach ($destinationTemplateObject in $destinationtemplatesobject) {
$templateCompareObject = $destinationtemplateobject.name.Substring(0, ($destinationtemplateobject.name.Length - $appendName.Length))
write-host $templateCompareObject
if ($templatesobject.name -contains $templateCompareObject) {
write-host "template present in source" -ForegroundColor Green
}
else {
log "Moving $destinationTemplateObject to old folder"
write-host "Moving $destinationTemplateObject to old folder"
#make sure 'old' folder exists
if (!(Get-Datacenter -Server $DestinationViServer $destinationDataCenter |get-folder $DestinationFolderName | get-folder -NoRecursion old)) {
New-Folder -Location (Get-Datacenter -Server $DestinationViServer $destinationDataCenter |get-folder $DestinationFolderName) -Name old
}
$oldFolderObject = Get-Datacenter -Server $DestinationViServer $destinationDataCenter |get-folder $DestinationFolderName | get-folder -NoRecursion old
move-template -template $destinationTemplateObject -Destination $oldFolderObject
set-template -template $destinationTemplateObject -Name ($destinationTemplateObject.Name + "-old-" + (get-date -format "yyyMMdd")) -confirm:$false
}
}
# Delete old templates older than one month
if ($cleanold) {
Write-Host "Removing old templates that are over 1 month old"
if ($DestinationFolderName -eq "legacy") {
write-host "Not needed in legacy folder"
}
else {
$oldDestinationTemplates = get-Datacenter -Server $DestinationViServer -Name $DestinationDataCenter | get-folder -Name $DestinationFolderName | get-folder old| get-template -NoRecursion
}
foreach ($oldDestinationTemplate in $oldDestinationTemplates) {
$oldTemplateObjectChangeDate = [datetime](Get-View $oldDestinationTemplate).Config.ChangeVersion
$indexDate = (get-date).AddDays(-30)
if ($oldTemplateObjectChangeDate -lt $indexDate) {
log "$oldDestinationTemplate created $oldTemplateObjectChangeDate will delete"
write-host "$oldDestinationTemplate created $oldTemplateObjectChangeDate will delete"
Remove-Template -DeletePermanently -Server $DestinationViServer -Template $oldDestinationTemplate -Confirm:$false
}
else {
write-host "$oldDestinationTemplate created $oldTemplateObjectChangeDate not old enough"
}
}
}
disconnect-viserver * -force -confirm:$false -ErrorAction SilentlyContinue
}
# #Prod Templates to VC01 CDC
Copy-Templates -SourceViServer vc01-test -DestinationViServer vc01 -DestinationDataStore CDC-Templates -SourceDataCenter CSIRO-TEST -DestinationDataCenter CSIRO -DestinationCluster "CDC Cluster09 (VI Management)" -DestinationNetworkName "CSIRO - VI Internal" -SourceFolderName prod -DestinationFolderName templates -cleanold #-setTemplateChangeDateFile
# #Legacy Templates to VC01 CDC
Copy-Templates -SourceViServer vc01-test -DestinationViServer vc01 -DestinationDataStore CDC-Templates -SourceDataCenter CSIRO-TEST -DestinationDataCenter CSIRO -DestinationCluster "CDC Cluster09 (VI Management)" -DestinationNetworkName "CSIRO - VI Internal" -SourceFolderName legacy -DestinationFolderName templates-legacy #-setTemplateChangeDateFile
# #Prod Templates to VC02 CMDC
Copy-Templates -SourceViServer vc01-test -DestinationViServer vc02 -DestinationDataStore CMDC-Templates -SourceDataCenter CSIRO-TEST -DestinationDataCenter CSIRO -DestinationCluster "CMDC Cluster7 (VI Management)" -DestinationNetworkName "CSIRO - VI Internal" -SourceFolderName prod -DestinationFolderName templates #-setTemplateChangeDateFile
# #Legacy Templates to VC02 CMDC
Copy-Templates -SourceViServer vc01-test -DestinationViServer vc02 -DestinationDataStore CMDC-Templates -SourceDataCenter CSIRO-TEST -DestinationDataCenter CSIRO -DestinationCluster "CMDC Cluster7 (VI Management)" -DestinationNetworkName "CSIRO - VI Internal" -SourceFolderName legacy -DestinationFolderName templates-legacy #-setTemplateChangeDateFile
# #Prod tempates to VC01 Self-service Brisbane
Copy-Templates -SourceViServer vc01-test -DestinationViServer vc01 -DestinationDataStore QLD-CL20-0808-SAS-2TB -SourceDataCenter CSIRO-TEST -DestinationDataCenter "Self-Service" -DestinationCluster "QLD Cluster 20 (General Self Service)" -DestinationNetworkName "Self-Service VI Internal" -SourceFolderName prod -DestinationFolderName templates -appendName "-bne" #-setTemplateChangeDateFile
# #desktop-prod tempates to VC01 Self-service Brisbane
Copy-Templates -SourceViServer vc01-test -DestinationViServer vc01 -DestinationDataStore QLD-CL20-0808-SAS-2TB -SourceDataCenter CSIRO-TEST -DestinationDataCenter "Self-Service" -DestinationCluster "QLD Cluster 20 (General Self Service)" -DestinationNetworkName "Self-Service VI Internal" -SourceFolderName desktop-prod -DestinationFolderName templates-desktop -appendName "-bne" #-setTemplateChangeDateFile
# #desktop-prod tempates to VC01 Self-service
#Copy-Templates -SourceViServer vc01-test -DestinationViServer vc01 -DestinationDataStore cl11-12dc-ssd-8TB -SourceDataCenter CSIRO-TEST -DestinationDataCenter "Self-Service" -DestinationCluster "CDC Cluster 11 (Enterprise Self Service)" -DestinationNetworkName "Self-Service VI Internal" -SourceFolderName desktop-prod -DestinationFolderName templates-desktop #-setTemplateChangeDateFile
Copy-Templates -SourceViServer vc01-test -DestinationViServer vc01 -DestinationDataStore CDC_NFS_Templates -SourceDataCenter CSIRO-TEST -DestinationDataCenter "Self-Service" -DestinationCluster "CDC Cluster 11 (General Self Service)" -DestinationNetworkName "Self-Service VI Internal" -SourceFolderName desktop-prod -DestinationFolderName templates-desktop #-setTemplateChangeDateFile
# Prod tempates to VC01 Self-service
Copy-Templates -SourceViServer vc01-test -DestinationViServer vc01 -DestinationDataStore CDC_NFS_Templates -SourceDataCenter CSIRO-TEST -DestinationDataCenter "Self-Service" -DestinationCluster "CDC Cluster 11 (General Self Service)" -DestinationNetworkName "Self-Service VI Internal" -SourceFolderName prod -DestinationFolderName templates -appendName "-netapp"#-setTemplateChangeDateFile
# #Prod Templates to VC01 WA
Copy-Templates -SourceViServer vc01-test -DestinationViServer vc01 -DestinationDataStore WA-CL3-c00-SAS-4TB -SourceDataCenter CSIRO-TEST -DestinationDataCenter CSIRO -DestinationCluster "Perth Cluster03 (Production)" -DestinationNetworkName "CSIRO - VI Internal" -SourceFolderName prod -DestinationFolderName templates -appendName "-wa" #-setTemplateChangeDateFile
# #Prod Templates to VC01-NGI vSAN
#Copy-Templates -SourceViServer vc01-test -DestinationViServer vc01-ngi -DestinationDataStore CL43-vsanDatastore -SourceDataCenter CSIRO-TEST -DestinationDataCenter vSAN -DestinationCluster "CDC Cluster43 (vSAN)" -DestinationNetworkName "vSAN-VI-Internal" -SourceFolderName prod -DestinationFolderName templates
# #Prod templates to vc01-test DEV
#Copy-Templates -SourceViServer vc01-test -DestinationViServer vc01-test -DestinationDataStore test-templates -SourceDataCenter CSIRO-TEST -DestinationDataCenter DEV -DestinationCluster "CDC cluster07 (Dev)" -DestinationNetworkName "DEV VI Internal" -SourceFolderName legacy -DestinationFolderName legacy-templates
#Copy-Templates -SourceViServer vc01-test -DestinationViServer vc01-test -DestinationDataStore CDC-CL7-1ea3-SSD-8TB -SourceDataCenter CSIRO-TEST -DestinationDataCenter DEV -DestinationCluster "CDC cluster07 (Dev)" -DestinationNetworkName "DEV VI Internal" -SourceFolderName prod -DestinationFolderName templates
log "Finished"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment