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
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
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
LucD you are legend.
I wish I had the time to be half the legend that Luc is.
[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
Hi Halr9000,
I got your book some time ago. Just want say that you done excellent job.
Regards,
DM
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?
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"} | % {
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
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?
Can you attach the modified script so I can have a look ?
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
$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!
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
Name | Path |
VM1 | DC1\directory1\directory2\VM1 |
VM2 | DC1\directory3\directory4\VM2 |
VM3 | DC2\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
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
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
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
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