I am moving from one virtual center to another. I have created a script that will recreate the datacenters and clusters.
I am having problems figuring out how to recreate the folders. These folders can be buried as far as 4 deep in hierarchy so even though I can do a get-folder and find the folders I am not sure how to put them back the way I they are laided out in the original VC
$1 = Get-Folder | where-object { $_.name -notlike "Discovered virtual machine"} |`
where-object { $_.name -notlike "vm"} | where-object { $_.name -notlike "Datacenters"}|`
where-object { $_.name -notlike "host"}
$1 | export-Clixml test.xml
The code above of course does not have (I don't think) the information to put the folders back in hierachy when I do -
$newfolder = Import-Clixml .\test.xml
$newfolder | foreach-Object{
Get-Folder -Name VM -Location $_.DataCenter | New-Folder -Name $_.Folder
}
Quick Note: Some of our folders are 4 levels deep
Any assistance appreciated.
Thanks
I also have to copy the resourcepool info so figuring out this step would help.
Trying this:
$new= New-Object System.Collections.ArrayList
$c = $null
$a = Get-Folder testvm
$count = 0
while(! ($c.name -eq "vm")){
$Info = "" |Select Bottom, Up, count
#$new = Get-Folder $a.name
$Info.bottom = $a
$b = $a.parentid
$c = get-folder -id $b
$Info.up = $c.name
$a = $c
$info.count = $count++
$New.add($Info)
}
I have this peice working but I still have to start the build from the vm level down
I created the following 2 function for this. Give it a try.
Just replace the $src and $dst parameters with the parameter that holds the connection to your vCenter server like this:
$src = Connect-VIServer "your vCenter server" -NotDefault
I've also attached a little text file with the functions.
-
#Export folder structure (no datacenter folders!) function Export-Folders { filter Get-FolderStructure { $folder = "" | select Name,Children $folder.Name = $_.name $folder.Children = @($_ | Get-Folder -NoRecursion | Get-FolderStructure ) $folder } $FolderStructure=@{} Get-Datacenter -Server $src | %{$FolderStructure[http://$_.name|http://$_.name] = $_ | Get-Folder -NoRecursion | Get-FolderStructure} $FolderStructure | Export-Clixml "Folders.xml" }
-
#Import folder structure (no datacenter folders!) function Import-Folders { $FolderStructure = Import-Clixml "Folders.xml" filter New-FolderStructure { param($parent) if (-not($folder = Get-Folder $_.name -Location $parent -ErrorAction:SilentlyContinue)) {$folder = New-Folder $_.name -Location $parent} $_.children | New-FolderStructure($folder) } $FolderStructure.GetEnumerator() | %{$dc = get-datacenter $_.name -server $dst; $_.value | New-FolderStructure($dc)} }
-
Arnim van Lieshout
If you find this information useful, please award points for "correct" or "helpful".
I created the following 2 function for this. Give it a try.
Just replace the $src and $dst parameters with the parameter that holds the connection to your vCenter server like this:
$src = Connect-VIServer "your vCenter server" -NotDefault
I've also attached a little text file with the functions.
-
#Export folder structure (no datacenter folders!) function Export-Folders { filter Get-FolderStructure { $folder = "" | select Name,Children $folder.Name = $_.name $folder.Children = @($_ | Get-Folder -NoRecursion | Get-FolderStructure ) $folder } $FolderStructure=@{} Get-Datacenter -Server $src | %{$FolderStructure[http://$_.name|http://$_.name] = $_ | Get-Folder -NoRecursion | Get-FolderStructure} $FolderStructure | Export-Clixml "Folders.xml" }
-
#Import folder structure (no datacenter folders!) function Import-Folders { $FolderStructure = Import-Clixml "Folders.xml" filter New-FolderStructure { param($parent) if (-not($folder = Get-Folder $_.name -Location $parent -ErrorAction:SilentlyContinue)) {$folder = New-Folder $_.name -Location $parent} $_.children | New-FolderStructure($folder) } $FolderStructure.GetEnumerator() | %{$dc = get-datacenter $_.name -server $dst; $_.value | New-FolderStructure($dc)} }
-
Arnim van Lieshout
If you find this information useful, please award points for "correct" or "helpful".
This script worked perfectly, I have to admit I don’t yet understand all of how it does what it does but I’m working on it. I created all my folders the way I wanted, I am running a test on how I can make sure the right VM’s get placed in those folders
Thank you for your help
#Export folder structure (no datacenter folders!)
function Export-Folders {
filter Get-FolderStructure {
#$src = Connect-VIServer vcusa -NotDefault
$folder = "" | select Name,Children,Vm
$folder.Name = $_.name
$folder.Children = @($_ | Get-Folder -NoRecursion | Get-FolderStructure )
$vmname = @(Get-VM -Location $_ -NoRecursion)
$folder.Vm = $vmname.name
$folder
}
$FolderStructure=@{}
Get-Datacenter -Server $src | %{$FolderStructure[http://$_.name|http://$_.name] = $_ | Get-Folder -NoRecursion | Get-FolderStructure}
$FolderStructure | Export-Clixml "Folders.xml"
}
I added the get-vm line to get the vm's under that folder so I could move it back into the folder
But I am not sure how to iterate throught the file to do the move-vm cmdlet? - Tips?
Exporting VMs and their locations:
#Export vm locations function Export-VmLocations { filter Get-Path { param($child) $folder = Get-View -Server $src $_.parent if ($folder.gettype().name -eq "Datacenter") { $child } else { $path = "" | select Name,Child $path.name = $folder.name $path.child = $child $folder | Get-Path($path) } } $VmLocations = @() foreach ($vm in Get-VM -Server $src) { $VmObj = "" | Select Name,Datacenter,Path $VmObj.Name = $vm.name $VmObj.Datacenter = $($vm | Get-Datacenter).name $VmObj.Path = $vm | Get-View | Get-Path $VmLocations += $VmObj } $VmLocations | Export-Clixml "VmLocations.xml" }
-
Import Vm's again:
#Import vm locations (Move vm's to original location) function Import-VmLocations { filter Get-VmLocation { param($parent) if ($_.child) { $_.child | Get-VmLocation(Get-Folder -Server $dst -Location $parent $_.Name) } else { Get-Folder -Server $dst -Location $parent $_.Name } } foreach ($vm in (Import-Clixml "VmLocations.xml")) { $dc = Get-Datacenter -Server $dst $vm.datacenter Move-VM ($dc | Get-VM $vm.Name) -Destination ($vm.path | Get-VmLocation($dc)) } }
-
Have fun!
Arnim van Lieshout
Blogging: http://www.van-lieshout.com
If you find this information useful, please award points for "correct" or "helpful".
This is EXACTLY what I am looking for, I've tried the export and create folder function it worked great I've not used the putting the vm's back in place yet but I'll be testing it this weekend
Apologies in advance.
Is there a way I can modify the folder and VM folder scripts to work on single Datacenters at a time. My requirement has changed and some folks would rather move one DC at a time vs. having the script just move all of the VC (we are also breaking off one of the DC's into their own VC).
If you change Arnim's Export-Folders function you can export only one datacenter. You have to change:
Get-Datacenter -Server $src
into:
Get-Datacenter -Name YourDatacenter -Server $src
If you want to use Arnim's Export-VmLocations function you have to change:
foreach ($vm in Get-VM -Server $src) {
into:
foreach ($vm in (Get-Datacenter -Name YourDatacenter | Get-VM -Server $src)) {
Robert
Message was edited by: RvdNieuwendijk
Thanks for the scripts, they work like a charm. Also on vSphere 4.1.
If you need to restore the folders and VM's to a new datacenter then change the following lines.
Import-Folders
$FolderStructure.GetEnumerator() | %{$dc = get-datacenter $_.name -server $dst; $_.value | New-FolderStructure($dc)}
into
$FolderStructure.GetEnumerator() | %{$dc = get-datacenter -Name "New_DataCenter" -server $dst; $_.value | New-FolderStructure($dc)}
Import-VM's
$dc = Get-Datacenter -Name $vm.datacenter -Server $dst
into
$dc = Get-Datacenter -Name "New_DataCenter" -Server $dst
If you found this or any other answer useful please consider the use of the Helpful or correct buttons to award points.
Regards
A. Mikkelsen
If you get an error while importing, check if you in the folders parent, is a sub folder with the same name as the one you are creating.
To get around the error, change the if statement in the filter (add -NoRecursion)
from
if (-not($folder = Get-Folder $_.name -Location $parent -ErrorAction:SilentlyContinue)) {$folder = New-Folder $_.name -Location $parent}
to
if (-not($folder = Get-Folder $_.name -Location $parent -ErrorAction:SilentlyContinue -NoRecursion)) {$folder = New-Folder $_.name -Location $parent}
If you found this or any other answer useful please consider the use of the Helpful or correct buttons to award points.
Regards
A. Mikkelsen