# encoding: ascii
# api: powershell
# title: Step02a-Export_VM-to-Fol
# description: Export vCenter Folder structure incl VM relations
# version: 0.1
# type: function
# author: Leon Scheltema
# license: CC0
# function: Copy-VCFolderStructure
# x-poshcode-id: 5664
# x-archived: 2015-01-15T20:03:19
# x-published: 2015-01-07T10:08:00
#
#
# Export vCenter Folder structure incl VM relations
# By Leon Scheltema AVANCE ICT Groep Nederland
# Functions used by Grzegorz Kulikowski / Robert van den Nieuwendijk
# Begin variables
$DefaultVIServers
$OldVC = "Old vCenter"
$NewVC = "New vCenter"
# End variables
# Connect to vCenter server
Connect-VIServer "$OldVC"
Connect-VIServer "$NewVC"
function Copy-VCFolderStructure {
<#
.SYNOPSIS
Copy-VCFolderStructure copies folder and its structure from one VC to another..
.DESCRIPTION
Copy-VCFolderStructure can be handy when doing migrations of clusters/hosts between
Virtual Center servers. It takes folder structure from 'old' VC and it recreates it on 'new'
VC. While doing this it will also output virtualmachine name and folderid. Why would you
want to have it ? Let's say that you have a cluster on old virtual center server
oldvc.local.lab
DC1\Cluster1\folder1
DC1\Cluster1\folderN\subfolderN
Copy-VCFolderStructure will copy entire folder structure to 'new' VC, and while doing this
it will output to screen VMs that resides in those structures. VM name that will be shown on
screen will show also folderid, this ID is the folderid on new VC. After you have migrated
your hosts from old cluster in old VC to new cluster in new VC, and folder structure is there,
you can use move-vm cmdlet with -Location parameter. As location you would have give the
folder object that corresponds to vm that is being moved. Property Name is the name of VM
that was discovered in that folder and Folder is the folderid in which the vm should be moved
into. This folderid has to first changed to folder, for example :
$folderobj=get-view -id $folder|Get-VIObjectByVIView
We can then use $folderobj as parameter to move-vm Location parameter
.PARAMETER OldFolder
This should be the extensiondata of folder that you want to copy to new VC.
$folderToRecreate=Get-Folder -Server oldVC.lab.local -Name teststruct
Have in mind that this should be an single folder and not an array.
.PARAMETER ParentOfNewFolder
When invoking the function this is the root folder where you want to attach the copied folder.
Let's say you are copying folder from \DatacenterA\FolderX\myfolder
If you will have the same structure on the new VC, you would have set ParentOfNew folder
to FolderX. Still it's not a problem if you have a new structure on new VC. Let's say that on
new VC you have folder: \DatacenterZ\NewStructure\FolderZ and you want to copy entire
'myfolder' beneath the FolderZ. In that case, first create a variable that has desired folder
$anchor=get-folder 'FolderZ' -Server newVC
Make sure that $anchor variable will have only 1 element.
.PARAMETER NewVC
This parameter describes virtual center to which we are copying the folder structure.
Copy-VCFolderStructure works only when you are connected to both old and new vc at the
same time. You need to set your configuration of PowerCLI to handle multiple connections.
Set-PowerCLIConfiguration -DefaultVIServerMode 'Multiple'
You can check if you are connected to both servers using $global:DefaultVIServers variable
.PARAMETER OldVC
This parameter describes virtual center from which we are copying the folder structure.
Copy-VCFolderStructure works only when you are connected to both old and new vc at the
same time. You need to set your configuration of PowerCLI to handle multiple connections.
Set-PowerCLIConfiguration -DefaultVIServerMode 'Multiple'
You can check if you are connected to both servers using $global:DefaultVIServers variable
.EXAMPLE
PS C:\> Set-PowerCLIConfiguration -DefaultVIServerMode 'multiple'
PS C:\> $DefaultVIServers
Ensure that you are connected to both VC servers
Establish variables:
This will be the folder that we will be copying from old VC
$folderToRecreate=Get-Folder -Server $OldVC -Name 'teststruct'
This will be the folder to which we will be copying the folder structure
$anchor=get-folder 'IWantToPutMyStructureHere' -Server $NewVC
$OldVC='myoldvc.lab.local'
$NewVC='mynewvc.lab.local'
Copy-VCFolderStructure -OldFolder $folderToRecreate.exensiondata -NewVC $NewVC
-OldVC $OldVC -ParentOfNewFolder $anchor
$OldFolder expects to get exensiondata object from the folder, if you will not provide it, function will
block it.
.EXAMPLE
If you are planning to move vms after hosts/vm/folders were migrated to new VC, you might use it in this way.
By default Copy-VCFolderStructure will output also vms and their folder ids in which they should reside on new
VC. You can grab them like this:
$vmlist=Copy-VCFolderStructure -OldFolder $folderToRecreate.exensiondata -NewVC $NewVC -OldVC $OldVC -ParentOfNewFolder $anchor
You can now export $vmlist to csv
$vmlist |export-csv -Path 'c:\migratedvms.csv' -NoTypeInformation
And once all virtual machines are in new virtual center, you can import this list and do move-vm operation on those
vms. Each vm has name and folder properties. Folder is a folderid value, which has to be converted to Folder object.
move-vm -vm $vmlist[0].name -Location (get-view -id $vmlist[0].folder -Server $newVC|get-viobjectbyviview) -Server $newVC
This would move vm that was residing in previously on old VC in migrated folder to its equivalent on new VC.
.NOTES
NAME: Copy-VCFolderStructure
AUTHOR: Grzegorz Kulikowski
NOT WORKING ? #powercli @ irc.freenode.net
THANKS: Huge thanks go to Robert van den Nieuwendijk for helping me out with the recursion in this function.
.LINK
http://psvmware.wordpress.com
#>
param(
[parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[VMware.Vim.Folder]$OldFolder,
[parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[VMware.VimAutomation.ViCore.Impl.V1.Inventory.FolderImpl]$ParentOfNewFolder,
[parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[string]$NewVC,
[parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[string]$OldVC
)
$NewFolder = New-Folder -Location $ParentOfNewFolder -Name $OldFolder.Name -Server $NewVC
Get-VM -NoRecursion -Location ($OldFolder|Get-VIObjectByVIView) -Server $OldVC|Select-Object Name, @{N='Folder';E={$NewFolder.id}}
foreach ($childfolder in $OldFolder.ChildEntity|Where-Object {$_.type -eq 'Folder'})
{
Copy-VCFolderStructure -OldFolder (Get-View -Id $ChildFolder -Server $OldVC) -ParentOfNewFolder $NewFolder -NewVC $NewVC -OldVC $OldVC
}
}
$folderToRecreate=Get-Folder -Server $OldVC
$anchor=get-folder vm -Server $NewVC
$vmlist=Copy-VCFolderStructure -OldFolder $folderToRecreate.extensiondata -NewVC $NewVC -OldVC $OldVC -ParentOfNewFolder $anchor
$vmlist |export-csv -Path "migratedvms.csv" -NoTypeInformation
# Disconnect from vCenter server
Disconnect-VIServer -server "*" -Force -Confirm:$false