How to copy folders structure between two virtual center servers ?


Hello !
It is some time since i posted last time. There was quite a lot happening in my life lately so that’s why 😉 I’ve spent huge amount of time on my first lecture that was given in Poland at PLVMUG,
plvmug.q1.2013-26-700x464 (1)
plvmug.q1.2013-24-700x464
after that i was back again in Poland to see my family on Easter. But anyway… i am lately having more free time, so i can share some of my thoughts with you again 😉
This time i want to show how we can copy folder structures between different virtual center servers. For example if you have to make a migration between virtual center servers, there is a lot to think of while doing this. You can’t forget about your annotations, folders(structure), location of virtual machines.
If you are migrating 20-50 vms, that’s not a big deal to move that kind of volume between VC, but what if you need to migrate 1000 or 2000 or 10000 vms ? And probably you don’t keep virtual machines inside ‘Discovered virtual machines’ folder, but you already have some structure.
This example was built based on example where cluster vms are attached to 1 folder structure. So if you have a virtual center and datacenter within, i assume here that structure looks like this:
‘blue\vm folders\’
‘\Datacenter X\ Cluster_Omega\Somefolder_with_Structure’

This function is able to move not only folder structures between VC but it also generates list of virtual machines and their folder ids, to which they should be moved. So if all my vms from cluster Omega resides somewhere in folder ‘Somefolder_with_Structure\x\y\z\’ you can grab the output of script to variable :
$mvlist=Copy-VCFolderStructure ….
While copying the folder structure this funtion will also return an array of vms with Name and Folder property, where the Folder property is actually an ID of a folder on the new virtual center server in which this vm should be placed.

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.extensiondata -NewVC $NewVC
		-OldVC $OldVC -ParentOfNewFolder $anchor
		$OldFolder expects to get extensiondata 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.extensiondata -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
		https://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
                  }
}

My example:
We have our VcOld: at : vc1.lab.local My cluster is CL_Holandia
$oldvc=vc.lab.local
$newvc=vc2.lab.loacl

main_dc_holandia
Our NewVC before the movement looks like this:
As you can see in dc_new there is a folder that should keep my folder structure called: ‘Some_Holder’

before_newvc

On NewVC we have now structure like this:
We are connected to 2 virtual center servers : vc.lab.local and vc2.lab.local
Our cluster folder is named CL_Holandia where we keep all vms that are inside the cluster.
We are defining folder to be copied from old_VC:
$folderToRecreate=get-folder -Server $oldVC -Name ‘CL_Holandia’
we define to which folder this structure should go:
$anchor=get-folder’CL_Holandia’ -Server $newVC
Where:
$oldvc=’vc.lab.local’
$newvc=’vc2.lab.local’
We store VMs in variable $Vmlist
$vmlist=Copy-VCFolderStructure -OldFolder $folderToRecreate.extensiondata -ParentOfNewFolder $Anchor -NewVC $NewVC
-OldVC $OldVC

copyFolderS

newVCfS
When we will add the cluster to new VC we will have structure probably like this. There will be additional ‘Discovered virtual machine’ folder, where all vms will appear and the rest of our copied structure. That means that we should now move vms to their proper folders.
clusteradded

After the last movement we will see proper structure:
It’s time now to move our vms from cluster from old VC, to folder of NEW cluster in NEW NC. So we will use now
$Vmlist variable do to this:
foreach($vm in $vmlist) {move-vm -vm $vm.name -destination (get-view -id $vm.folder|get-viobjectbyviview)}
This should do it. We should see now our structure with vms and folder in proper place.
afterconfandmovement
I do realize that i write this post at 1 am, but this is the only time i guess now that i have it free… So i know there might be some issues/bugs with this code. Please post a comment whenever you see some error. I will try to fix it as soon as possible. Please note that not all of you should have the same setup as me. This solution in regards of moving vms on new VC to proper folders will work only if you have similar folder structure(1 CL x 1 main_folder). I will try to rewrite this function entirely in order to make it as compatible with all structures as it can be.
At the end i would like to thank to Robert van den Nieuwendijk for his time and effort in writing this function. Without him it would take ages for me to write this recursion…
I hope that this function will help some of you with similar setup when you need to do migrations.

*images from PLVMUG session were taken from:
Blog.Inleo.Pl

Advertisements

19 thoughts on “How to copy folders structure between two virtual center servers ?

  1. I don’t know if you read these comments, but have you ever tried adding code to this script to also copy vcenter folder permissions as well?

    Matt

    • Hi Matt, that’s doable, depends on some factors though. For example
      1) what if perm is inherited from some parent and on the destination you do not have that parent, so do you want to have it attached on direct basis or would you want to still to point to to parent in higher level ?
      2) if you have for example on folderes only permissions that are directly attached to that object that would be simple
      3) what if those are mixed perms, inherited and assigned to that folder object, what then ? do you want to break inheritance and attach that perm to the folder directly ?

      Let me know how do you see it, and i will try to add that functionality for you.

      • Thanks. I would be in scenario 3, Ideally copying both inherited and explicit folder permissions, but likely 99% of my inherited perms are set at the DC or Vcenter level. I’m currently configuring a 2nd vcenter in linked mode(brand new) and want an exact duplication of the vc1 folder structure on vc2. We can take this discussion offline to email if that’s preferred.
        Matt

  2. Hi I am using this to migrate to another vcenter, it makes the new folders in the destination just fine, the issue is when I try to move the vm’s into the folders the folder ID is different and the vm’s do not go to the correct folder.

    Is there another step that matches the folder id’s old = new ?

  3. Hello,

    Thanks for the script.

    I’m trying to copy from root folder to root folder, but it appear that the function always create the folder defined in $Anchor (which is creating a vm folder for my environment).

    How can I avoid this issue ?

    Best regards.

  4. Hi psvmware, Thanks for a great script. I am working on almost identical situation and could use some pointers. can we chat via email for a few minutes?

    • PowerCLI C:\> Copy-VCFolderStructure

      cmdlet Copy-VCFolderStructure at command pipeline position 1
      Supply values for the following parameters:
      OldFolder: MIS
      ParentOfNewFolder: MIS
      NewVC: melradvcw01.prod.quest.corp
      OldVC: melradvcw02.prod.quest.corp
      Copy-VCFolderStructure : Cannot process argument transformation on parameter ‘OldFolder’. Cannot convert the “MIS” value of type “System.String” to
      type “VMware.Vim.Folder”.
      At line:1 char:1
      + Copy-VCFolderStructure
      + ~~~~~~~~~~~~~~~~~~~~~~
      + CategoryInfo : InvalidData: (:) [Copy-VCFolderStructure], ParameterBindingArgumentTransformationException
      + FullyQualifiedErrorId : ParameterArgumentTransformationError,Copy-VCFolderStructure

      • Please read the post again, it’s all explained how to get the folders. take a look on:

        It shows you how to fetch folders, you can’t just give a ‘name’ like you are doing, as that does not identify anything in particular. I hope you will get it from looking at that picture.

      • I did all those steps yesterday and it kept failing with the error above… I did it again this morning and it just worked… I’m not sure what happened!

        Is there any way to get it so it the folder imports directly under the datacenter rather than into a folder I have to initially create? Right now I have to create a duplicate and unnecessary folder to do the import… I guess worst case scenario, I’ll just move the whole folder structure after the migration.

      • Yes, there is , you just need to move anchor 1 level up. That’s the “vm” folder of datacenter.
        (get-view -id (get-datacenter ‘your datacenter for example’).Extensiondata.VmFolder).moref -> that’s the root one (vm folder) of Datacenter object.

  5. While running these commands, I am getting below error:-
    PowerCLI C:\> $vmlist=Copy-VCFolderStructure -OldFolder $folderToRecreate.extens
    iondata -ParentOfNewFolder $Anchor -NewVC $NewVC -OldVC $OldVC
    Copy-VCFolderStructure : The term ‘Copy-VCFolderStructure’ is not recognized
    as the name of a cmdlet, function, script file, or operable program. Check the
    spelling of the name, or if a path was included, verify that the path is
    correct and try again.
    At line:1 char:9
    + $vmlist=Copy-VCFolderStructure -OldFolder $folderToRecreate.extensiondata
    -Paren …
    + ~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : ObjectNotFound: (Copy-VCFolderStructure:String)
    [], CommandNotFoundException
    + FullyQualifiedErrorId : CommandNotFoundException

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s