VMware Cloud Community
munizaba
Contributor
Contributor
Jump to solution

Folder migration

We are in the process of decommissioning one of the VC. I'm going to move all ESX host and VMs to new Virtual Centre. Only problem I have is the folders migration. (we have 300 VMs that are spread in some 20-40 folders)

Is there a way that I can create script that will place VMs in correct folder. I was thinking something like I can export VM folder membership to file and use that file to populate folders on new VC.

Thank,

DM

1 Solution

Accepted Solutions
LucD
Leadership
Leadership
Jump to solution

Are the folders already created on the new VC ?

I assume that all the ESX hosts were already moved and that the guests are now under the Datacenter in the new VC.

The following script comes from and will write to a CSV file all the guests and the blue folder path where they are located.

filter Get-FolderPath {
	$_ | Get-View | % {
		$row = "" | select Name, Path
		$row.Name = $_.Name

		$current = Get-View $_.Parent
		$path = $_.Name
		do {
			$parent = $current
			if($parent.Name -ne "vm"){$path = $parent.Name + "\" + $path}
			$current = Get-View $current.Parent
		} while ($current.Parent -ne $null)
		$row.Path = $path
		$row
	}
}

$report = Get-VM | Get-Folderpath
$report | Export-Csv "c:\VM-with-FolderPath.csv" -NoTypeInformation

With the CSV file you can now run the following script against the new VC and move all the guests in the correct folder.

$hashTab = @{}
$folder = Get-View -ViewType Folder
$folder += (Get-View -ViewType Datacenter)
$folder | where {$_.Name -ne "host" -and $_.Name -ne "vm"} | % {
	$current = $_
	$path = "" 
	do {
		$parent = $current
		if($parent.Name -ne "vm"){$path = $parent.Name + "\" + $path}
		$current = Get-View $current.Parent
	} while ($current.Parent -ne $null)
	$hashTab[$path] = $_
}

$VMfolder = import-csv "c:\VM-with-FolderPath.csv" | Sort-Object -Property Path
foreach($guest in $VMfolder){
	$key = $guest.Path.Substring(0, $guest.Path.LastIndexOf("\") + 1)
	Move-VM (Get-VM $guest.Name) -Destination (Get-VIObjectByVIView -MORef $hashTab[$key].MoRef) -WhatIf
}

Since this 2nd script contains square brackets I attached it.


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

View solution in original post

Reply
0 Kudos
24 Replies
LucD
Leadership
Leadership
Jump to solution

Are the folders already created on the new VC ?

I assume that all the ESX hosts were already moved and that the guests are now under the Datacenter in the new VC.

The following script comes from and will write to a CSV file all the guests and the blue folder path where they are located.

filter Get-FolderPath {
	$_ | Get-View | % {
		$row = "" | select Name, Path
		$row.Name = $_.Name

		$current = Get-View $_.Parent
		$path = $_.Name
		do {
			$parent = $current
			if($parent.Name -ne "vm"){$path = $parent.Name + "\" + $path}
			$current = Get-View $current.Parent
		} while ($current.Parent -ne $null)
		$row.Path = $path
		$row
	}
}

$report = Get-VM | Get-Folderpath
$report | Export-Csv "c:\VM-with-FolderPath.csv" -NoTypeInformation

With the CSV file you can now run the following script against the new VC and move all the guests in the correct folder.

$hashTab = @{}
$folder = Get-View -ViewType Folder
$folder += (Get-View -ViewType Datacenter)
$folder | where {$_.Name -ne "host" -and $_.Name -ne "vm"} | % {
	$current = $_
	$path = "" 
	do {
		$parent = $current
		if($parent.Name -ne "vm"){$path = $parent.Name + "\" + $path}
		$current = Get-View $current.Parent
	} while ($current.Parent -ne $null)
	$hashTab[$path] = $_
}

$VMfolder = import-csv "c:\VM-with-FolderPath.csv" | Sort-Object -Property Path
foreach($guest in $VMfolder){
	$key = $guest.Path.Substring(0, $guest.Path.LastIndexOf("\") + 1)
	Move-VM (Get-VM $guest.Name) -Destination (Get-VIObjectByVIView -MORef $hashTab[$key].MoRef) -WhatIf
}

Since this 2nd script contains square brackets I attached it.


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

Reply
0 Kudos
munizaba
Contributor
Contributor
Jump to solution

LucD you are legend.

Reply
0 Kudos
halr9000
Commander
Commander
Jump to solution

I wish I had the time to be half the legend that Luc is. Smiley Happy



[vExpert|http://www.vmware.com/communities/vexpert/], PowerShell MVP, VI Toolkit forum moderator

Author of the book: Managing VMware Infrastructure with PowerShell

Co-Host, PowerScripting Podcast (http://powerscripting.net)

Need general, non-VMware-related PowerShell Help? Try the forums at PowerShellCommunity.org

My signature used to be pretty, but then the forum software broked it. vExpert. Microsoft MVP (Windows PowerShell). Author, Podcaster, Speaker. I'm @halr9000
Reply
0 Kudos
munizaba
Contributor
Contributor
Jump to solution

Hi Halr9000,

I got your book some time ago. Just want say that you done excellent job.

Regards,

DM

Reply
0 Kudos
munizaba
Contributor
Contributor
Jump to solution

I have some problem with the script. Could you please check attached image when you have time.

kind regards,

DM

Reply
0 Kudos
racerzer0
Contributor
Contributor
Jump to solution

LucD.. this is exactly what I needed.. am doing the same thing as the original poster. However I am getting an error with the 2nd script.. where the actual move takes place:

The argument cannot be null or empty.

At :line:11 char:21

+ $current = Get-View <<<< $current.Parent

Any idea what's wrong?

Reply
0 Kudos
racerzer0
Contributor
Contributor
Jump to solution

I figured this out... forgot to mention this was being run against vSphere vCenter. So I had to add an exclude statement for Datacenters, along with vm and hosts.

$folder | where {$_.Name -ne "host" -and $_.Name -ne "vm" -and $_.Name -ne "Datacenters"} | % {

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

You're right, the Datacenters folder should be excluded as well since it doesn't have any parent.


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

Reply
0 Kudos
zenivox
Hot Shot
Hot Shot
Jump to solution

I modified the original script by adding the exclusion of the datacenter however now when I Iaunch the script it stays for about half an hour doing nothing and then I see:

Get-VIObjectByVIView: cannot validate argument on parameter 'MORef'. The argument is null or empty. Supply an argument..........

any suggestion?

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

Can you attach the modified script so I can have a look ?


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

Reply
0 Kudos
zenivox
Hot Shot
Hot Shot
Jump to solution

$hashTab = @{}

$folder = Get-View -ViewType Folder

$folder += (Get-View -ViewType Datacenter)

$folder | where {$_.Name -ne "host" -and $_.Name -ne "vm" -and $_.Name -ne "Datacenters"} | % {

    $current = $_

    $path = ""

    do {

        $parent = $current

        if($parent.Name -ne "vm"){$path = $parent.Name + "\" + $path}

        $current = Get-View $current.Parent

    } while ($current.Parent -ne $null)

    $hashTab[$path] = $_

}

$VMfolder = import-csv "C:\Users\xxxxxx\Music\VM-VLC-FolderPath.csv" | Sort-Object -Property Path

foreach($guest in $VMfolder){

    $key = $guest.Path.Substring(0, $guest.Path.LastIndexOf("\") + 1)

    Move-VM (Get-VM $guest.Name) -Destination (Get-VIObjectByVIView -MORef $hashTab[$key].MoRef) -WhatIf

}

The script continued running throwing same error over and over and in the end didn't move any VM. Many thanks for your time!

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

Just to make sure, your CSV looks something like this

Path

name1\name2\name3\

name4\

name5\name6

It would also be useful if you could check what is in $hashtab.

Do a

$hashtab.GetEnumerator()


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

Reply
0 Kudos
zenivox
Hot Shot
Hot Shot
Jump to solution

NamePath
VM1DC1\directory1\directory2\VM1
VM2DC1\directory3\directory4\VM2
VM3DC2\directory5\directory4\VM3

Precisely that is how the csv file looks like, it was created by using the first script you created. Unfortunately we have some directory names duplicated. The hashtab enumerator replies the following:

PowerCLI C:\Program Files (x86)\VMware\Infrastructure\vSphere PowerCLI> $hashtab.GetEnumerator()

You cannot call a method on a null-valued expression.

At line:1 char:1

+ $hashtab.GetEnumerator()

+ ~~~~~~~~~~~~~~~~~~~~~~~~

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

    + FullyQualifiedErrorId : InvokeMethodOnNull

I have the impression my powercli setup is missing something.... by the way I have powercli v.6

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

Ok, that seems ot indicate that $hashtab is empty.

Do the following lines return anything ?

$folder = Get-View -ViewType Folder

$folder += (Get-View -ViewType Datacenter)

$folder | where {$_.Name -ne "host" -and $_.Name -ne "vm" -and $_.Name -ne "Datacenters"}


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

Reply
0 Kudos
zenivox
Hot Shot
Hot Shot
Jump to solution

morning LucD, the first two returns nothing (not even an error), while the third returns what it seems an inventory state.. see screenshot

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

Can you try changing your CSV file to this format ?

In the content you showed, it doesn't seem to be a comma separated values (CSV) file.

Name,Path

VM1,DC1\directory1\directory2\VM1

VM2,DC1\directory3\directory4\VM2

VM3,DC2\directory5\directory4\VM3


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

Reply
0 Kudos
zenivox
Hot Shot
Hot Shot
Jump to solution

I modified the script and as usual it's taking its time to produce any sort of output...  I'll let you know in a bit

UPDATE: after an hour is still there doing nothing.. no output whatsover

UPDATE2: I modified the script by removing the exclusion of DC folder. Basically I reverted to:

$folder | where {$_.Name -ne "host" -and $_.Name -ne "vm"} | % {

and now it's throwing this error:

Get-View : Cannot validate argument on parameter 'VIObject'. The argument is

null or empty. Supply an argument that is not null or empty and then try the

command again.

At C:\Users\xxxxxx\xxxxx\VM-move-to-folder.ps1:10 char:23

+         $current = Get-View $current.Parent

+                             ~~~~~~~~~~~~~~~

    + CategoryInfo          : InvalidData: (:) [Get-View], ParameterBindingVal

   idationException

    + FullyQualifiedErrorId : ParameterArgumentValidationError,VMware.VimAutom

   ation.ViCore.Cmdlets.Commands.DotNetInterop.GetVIView

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

You lost me I'm afraid :smileygrin:

To start from a clean situation, can you attach the script your are currently using, as a file to this thread.

A sample extract of the CSV you are using. Make sure to make the names unrecognisable, I just want to see the layout of the file.


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

Reply
0 Kudos
zenivox
Hot Shot
Hot Shot
Jump to solution

Hi Luc, many thanks! Attached you'll find the files. In the csv file I renamed only the VM names and I chopped the lenght.

Reply
0 Kudos