As I promised in a previous post I wanted to migrate from a vCenter to whole new machine
Process was:
- Export folders
- Export VM locations in Folders
- Export Permissions
- Export Custom Attributes
- Create Folders on the new vCenter
- Disable DRS/HA
- Remove ESX hosts from Source vCenter and add to Destination vCenter
- Enable DRS/HA again
- Move all vm’s to correct folders
- Apply the permissions back
- Apply custom attributes and notes
Here is the script
1: #load Vmware Module
2: Add-PSSnapin VMware.VimAutomation.Core 3: 4: #Change to multi-mode vcenter management
5: Set-PowerCLIConfiguration -DefaultVIServerMode Multiple -Confirm:$false
6: 7: #Get vCenter Server Names
8: $sourceVI = Read-Host "Please enter the name of the source Server";
9: $destVI = Read-Host "Please enter the name of the destination Server"
10: 11: $creds = get-credential
12: 13: $datacenter = Read-Host "Please give the name of the datacenter you would like to run against"
14: 15: 16: #Connect to Source vCenter
17: connect-viserver -server $sourceVI -credential $creds18: connect-viserver -server $destVI -credential $creds -NotDefault:$false
19: 20: 21: filter Get-FolderPath {
22: $_ | Get-View | % {
23: $row = "" | select Name, Path
24: $row.Name = $_.Name 25: 26: $current = Get-View $_.Parent
27: $path = $_.Name28: do {
29: $parent = $current30: if($parent.Name -ne "vm"){$path = $parent.Name + "\" + $path}
31: $current = Get-View $current.Parent
32: } while ($current.Parent -ne $null)
33: $row.Path = $path 34: $row 35: } 36: } 37: 38: ## Export all folders 39: $report = @()40: $report = get-datacenter $datacenter -Server $sourceVI| Get-folder vm | get-folder | Get-Folderpath
41: ##Replace the top level with vm
42: foreach ($line in $report) {
43: $line.Path = ($line.Path).Replace($datacenter + "\","vm\")
44: }45: $report | Export-Csv "c:\Folders-with-FolderPath-$($datacenter).csv" -NoTypeInformation
46: 47: ##Export all VM locations 48: $report = @()49: $report = get-datacenter $datacenter -Server $sourceVI| get-vm | Get-Folderpath
50: 51: $report | Export-Csv "c:\vms-with-FolderPath-$($datacenter).csv" -NoTypeInformation
52: 53: 54: #Get the Permissions
55: 56: $folderperms = get-datacenter $datacenter -Server $sourceVI | Get-Folder | Get-VIPermission
57: $vmperms = Get-Datacenter $datacenter -Server $sourceVI | get-vm | Get-VIPermission
58: 59: $permissions = get-datacenter $datacenter -Server $sourceVI | Get-VIpermission
60: 61: $report = @()62: foreach($perm in $permissions){
63: $row = "" | select EntityId, FolderName, Role, Principal, IsGroup, Propagate
64: $row.EntityId = $perm.EntityId65: $Foldername = (Get-View -id $perm.EntityId).Name
66: $row.FolderName = $foldername 67: $row.Principal = $perm.Principal 68: $row.Role = $perm.Role 69: $row.IsGroup = $perm.IsGroup 70: $row.Propagate = $perm.Propagate 71: $report += $row 72: } 73: 74: foreach($perm in $folderperms){
75: $row = "" | select EntityId, FolderName, Role, Principal, IsGroup, Propagate
76: $row.EntityId = $perm.EntityId77: $Foldername = (Get-View -id $perm.EntityId).Name
78: $row.FolderName = $foldername 79: $row.Principal = $perm.Principal 80: $row.Role = $perm.Role 81: $row.IsGroup = $perm.IsGroup 82: $row.Propagate = $perm.Propagate 83: $report += $row 84: } 85: 86: foreach($perm in $vmperms){
87: $row = "" | select EntityId, FolderName, Role, Principal, IsGroup, Propagate
88: $row.EntityId = $perm.EntityId89: $Foldername = (Get-View -id $perm.EntityId).Name
90: $row.FolderName = $foldername 91: $row.Principal = $perm.Principal 92: $row.Role = $perm.Role 93: $row.IsGroup = $perm.IsGroup 94: $row.Propagate = $perm.Propagate 95: $report += $row 96: } 97: 98: $report | export-csv "c:\perms-$($datacenter).csv" -NoTypeInformation
99: 100: ##Export VM Custom Attributes and notes
101: 102: $vmlist = get-datacenter $datacenter -Server $sourceVI| get-vm
103: $Report =@()104: foreach ($vm in $vmlist) {
105: $row = "" | Select Name, Notes, Key, Value, Key1, Value1
106: $row.name = $vm.Name107: $row.Notes = $vm | select -ExpandProperty Notes
108: $customattribs = $vm | select -ExpandProperty CustomFields
109: $row.Key = $customattribs[0].Key 110: $row.Value = $customattribs[0].value 111: $row.Key1 = $customattribs[1].Key 112: $row.Value1 = $customattribs[1].value 113: $Report += $row 114: } 115: 116: $report | Export-Csv "c:\vms-with-notes-and-attributes-$($datacenter).csv" -NoTypeInformation
117: 118: 119: ##Disconnect-VIServer -Server $sourceVI -force -confirm:$false
120: 121: 122: #connect to Destination Server
123: ##connect-viserver -server $destVI -credential $creds -confirm:$false
124: 125: 126: ##IMPORT FOLDERS127: $vmfolder = Import-Csv "c:\Folders-with-FolderPath-$($datacenter).csv" | Sort-Object -Property Path
128: 129: foreach($folder in $VMfolder){
130: $key = @()131: $key = ($folder.Path -split "\\")[-2]
132: if ($key -eq "vm") {
133: get-datacenter $datacenter -Server $destVI | get-folder vm | New-Folder -Name $folder.Name
134: } else {
135: get-datacenter $datacenter -Server $destVI | get-folder vm | get-folder $key | New-Folder -Name $folder.Name
136: } 137: } 138: 139: ##ESX host migration 140: 141: #Switch off HA142: Get-Cluster $datacenter -Server $sourceVI | Set-Cluster -HAEnabled:$false -DrsEnabled:$false -Confirm:$false
143: 144: #Remove ESX hosts from old vcenter145: $Myvmhosts = get-datacenter $datacenter -Server $sourceVI | Get-VMHost
146: foreach ($line in $Myvmhosts) {
147: Get-vmhost -Server $sourceVI -Name $line.Name | Set-VMHost -State "Disconnected" -Confirm:$false
148: Get-VMHost -server $sourceVI -Name $line.Name | Remove-VMHost -Confirm:$false
149: }150: #add ESX hosts into new vcenter
151: foreach ($line in $Myvmhosts) {
152: Add-VMHost -Name $line.name -Location (Get-Datacenter $datacenter -server $destVI) -user root -Password trunk@1 -Force
153: } 154: 155: #Turn on HA and DRS on
156: Set-Cluster -Server $destVI Cluster1 -DrsEnabled:$true -HAEnabled:$true -Confirm:$false
157: 158: Disconnect-VIServer $sourceVI -Confirm:$false
159: 160: ##workaround for non working new-vipermissions
161: 162: function New-VIAccount($principal) {
163: $flags = [System.Reflection.BindingFlags]::NonPublic -bor [System.Reflection.BindingFlags]::Public -bor [System.Reflection.BindingFlags]::DeclaredOnly -bor [System.Reflection.BindingFlags]::Instance
164: 165: $method = $defaultviserver.GetType().GetMethods($flags) | where { $_.Name -eq "VMware.VimAutomation.Types.VIObjectCore.get_Client" }
166: $client = $method.Invoke($global:DefaultVIServer, $null)
167: Write-Output (New-Object VMware.VimAutomation.Client20.PermissionManagement.VCUserAccountImpl -ArgumentList $principal, "", $client)
168: } 169: 170: ##move the vm's to correct location
171: $VMfolder = @()172: $VMfolder = import-csv "c:\VMs-with-FolderPath-$($datacenter).csv" | Sort-Object -Property Path
173: foreach($guest in $VMfolder){
174: $key = @() 175: $key = Split-Path $guest.Path | split-path -leaf176: Move-VM (get-datacenter $datacenter -Server $destVI | Get-VM $guest.Name) -Destination (get-datacenter $datacenter -Server $destVI | Get-folder $key)
177: } 178: 179: 180: ##Import VM Custom Attributes and Notes
181: $NewAttribs = Import-Csv "C:\vms-with-notes-and-attributes-$($datacenter).csv"
182: 183: foreach ($line in $NewAttribs) {
184: set-vm -vm $line.Name -Description $line.Notes -Confirm:$false
185: Set-CustomField -Entity (get-vm $line.Name) -Name $line.Key -Value $line.Value -confirm:$false
186: Set-CustomField -Entity (get-vm $line.Name) -Name $line.Key1 -Value $line.Value1 -confirm:$false
187: 188: } 189: 190: 191: ##Import Permissions 192: $permissions = @()193: $permissions = Import-Csv "c:\perms-$($datacenter).csv"
194: 195: foreach ($perm in $permissions) {
196: $entity = ""
197: $entity = New-Object VMware.Vim.ManagedObjectReference
198: 199: switch -wildcard ($perm.EntityId) 200: { 201: Folder* { 202: $entity.type = "Folder"
203: $entity.value = ((get-datacenter $datacenter | get-folder $perm.Foldername).ID).Trimstart("Folder-")
204: } 205: VirtualMachine* { 206: $entity.Type = "VirtualMachine"
207: $entity.value = ((get-datacenter $datacenter | Get-vm $perm.Foldername).Id).Trimstart("VirtualMachine-")
208: } 209: }210: $setperm = New-Object VMware.Vim.Permission
211: $setperm.principal = $perm.Principal212: if ($perm.isgroup -eq "True") {
213: $setperm.group = $true
214: } else {
215: $setperm.group = $false
216: }217: $setperm.roleId = (Get-virole $perm.Role).id
218: if ($perm.propagate -eq "True") {
219: $setperm.propagate = $true
220: } else {
221: $setperm.propagate = $false
222: } 223: 224: $doactual = Get-View -Id 'AuthorizationManager-AuthorizationManager'
225: $doactual.SetEntityPermissions($entity, $setperm) 226: } 227: 228: ##Error Checking
229: ################ 230: 231: ##Gather all info for New Vcenter
232: ##Export all folders 233: $report = @()234: $report = Get-folder vm -server $destVI | get-folder | Get-Folderpath
235: ##Replace the top level with vm
236: foreach ($line in $report) {
237: $line.Path = ($line.Path).Replace("DC1\","vm\")
238: }239: $report | Export-Csv "c:\Folders-with-FolderPath_dest.csv" -NoTypeInformation
240: 241: ##Export all VM locations 242: $report = @()243: $report = get-vm -server $destVI | Get-Folderpath
244: 245: $report | Export-Csv "c:\vms-with-FolderPath_dest.csv" -NoTypeInformation
246: 247: 248: #Get the Permissions
249: $permissions = Get-VIpermission -Server $destVI
250: 251: $report = @()252: foreach($perm in $permissions){
253: $row = "" | select EntityId, FolderName, Role, Principal, IsGroup, Propopgate
254: $row.EntityId = $perm.EntityId255: $Foldername = (Get-View -id $perm.EntityId).Name
256: $row.FolderName = $foldername 257: $row.Principal = $perm.Principal 258: $row.Role = $perm.Role 259: $report += $row 260: }261: $report | export-csv "c:\perms_dest.csv" -NoTypeInformation
262: 263: ##Export VM Custom Attributes and notes
264: 265: $vmlist = get-vm -Server $destVI
266: $Report =@()267: foreach ($vm in $vmlist) {
268: $row = "" | Select Name, Notes, Key, Value, Key1, Value1
269: $row.name = $vm.Name270: $row.Notes = $vm | select -ExpandProperty Notes
271: $customattribs = $vm | select -ExpandProperty CustomFields
272: $row.Key = $customattribs[0].Key 273: $row.Value = $customattribs[0].value 274: $row.Key1 = $customattribs[1].Key 275: $row.Value1 = $customattribs[1].value 276: $Report += $row 277: } 278: 279: $report | Export-Csv "c:\vms-with-notes-and attributes_dest.csv" -NoTypeInformation
280: 281: ##compare the source and destination - this part is not yet finished
282: write-output "Folder-paths"
283: Compare-Object -ReferenceObject (import-csv C:\vms-with-FolderPath.csv) (import-csv C:\vms-with-FolderPath_dest.csv) -IncludeEqual
284: 285: 286: write-output "Notes & Attributes"
287: Compare-Object -ReferenceObject (import-csv "C:\vms-with-notes-and attributes.csv") (import-csv "C:\vms-with-notes-and attributes_dest.csv") -IncludeEqual
288: 289: write-output "Permissions"
290: Compare-Object -ReferenceObject (import-csv C:\perms.csv | select * -ExcludeProperty EntityId) (import-csv C:\perms_dest.csv | select * -ExcludeProperty EntityId) -IncludeEqual
291: Disconnect-VIServer -Server $destVI -Force -confirm:$false
292: The script is commented pretty well throughout the script, I will update with more and a walkthrough of the script later.
Give me a shout if you have any questions with the script
The script can also be downloaded below
22 comments:
Great script Maish, seriously good stuff
Very cool script! excellent work Maish!
Maish,
You saved my day!. I was working on something similar. Need to build a new vCenter database as our current has some corruptions.
Although I'm missing some stuff.
-export/import clusters
-export/import resource pools
-export/import DRS affinity rules
-export/import roles
-export/import Scheduled tasks
-export/import vcenter server settings
-export/import Customization specifications. I posted a script for this a while ago. http://www.van-lieshout.com/2009/07/export-and-import-customization-profiles-using-powershell/
maybe to be included in a future release ;-)
Major credits increase, my friend :-)
Keep the good stuff coming.
@avliesthout
Export DRS affinity rules: http://ict-freak.nl/2009/09/06/powercli-export-and-import-drs-rules-v2/
Alan, Avlieshout and Afokkema, thank you all for your enthusiasm.
True this is a version 1.0, this was done specifically for my environment and therefore not all things were included.
There were some quirks with the Templates as well, that will have to come in a future version.
I am sure that all of you will be able to build on this into a bigger and more comprehensive script.
Alan, Avlieshout and Afokkema, thank you all for your enthusiasm.
True this is a version 1.0, this was done specifically for my environment and therefore not all things were included.
There were some quirks with the Templates as well, that will have to come in a future version.
I am sure that all of you will be able to build on this into a bigger and more comprehensive script.
Hi there. Having some trouble with: $key = ($folder.Path -split "\\")[-2]
Error: you must provide a value expression on the right-hand side of the '-or' operator
Any chance you can help?
Hello,
I tried to use the script customizing it slightly to fit my environment. The export process works well, but the import process completely failed. I haven't had time yet to work out what the issue was but I was wondering if you had problems getting the import process to work as well. Atleast with the export process I had and will continue to have a backup of that data. :) Thanks,
Tony
Wow... you just saved me a bunch of time!!!! Thank you!
Hello Everyone,
I found my problem. I was using the same folder names in different parent folders. This was causing $entity.value = ((get-datacenter $datacenter | get-folder $perm.Foldername).ID).Trimstart("Folder-") to fail.
Thanks to anyone who looking into this matter.
Thanks again for the script.
Terry
Thanks for the update on you solution Terrry, I am glad you figured it out.
I am happy that you could make use of it tylopes.
I am experiencing the same issue. Did you manage to resolve?
Can you please explain what the problems you are experiencing?
Can you give a description of what your folder structure is like?
Probably the reason is that "-split" operator is only available in PowerShell 2.0.
You should mention in the article that PowerShell 2.0 is required to run the script.
Great script
Thank you Michael for pointing this out - I will update the script.
first thanks for this script
which part sould i use when i ONLY want to export and import Custom Attributes ?
Does this work for a move from 5.0 to 5.1?
Hi Natasha, I have not tried this in 5.x versions - so I cannot say.
If you do try, I would be interested in hearing how it turned out for you.
How does this script woth with vDS?
Hi Maish;
Is there a way to migrate VMs from one vCenter to another "without" removing and re-adding the ESXi hosts?? To be brief, I'm trying to migrate VMs and their corresponding folders/permissions from vCenter 4.1 to vCenter 5.1. Moving the hosts creates certain obstacles because of networking (vSS versus vDS) and ESXi licensing. Have you or anyone else had any success using this script in a vSphere/vCenter 5.1 environment?
I haven't been able to locate any PowerCli script yet that will help facilitate my requirement. Any help you can provide would be appreciated. Thanks.
Ron
Hello Maish,
I found your script and it looks like exactly what I need.
I am trying to use your script and have run into the following error during test of the "Import Permissons" section of the script.
Method invocation failed because [System.Object[]] doesn't contain a method named 'SetEntityPermissions'.
At H:\Scripts\PowerShell\snippet.ps1:54 char:35
+ $doactual.SetEntityPermissions <<<< ($entity, $setperm)
+ CategoryInfo : InvalidOperation: (SetEntityPermissions:String) [], RuntimeException
+ FullyQualifiedErrorId : MethodNotFound
If I $doactual | gm I see:
SetEntityPermissions Method System.Void SetEntityPermissions(VMware.Vim.ManagedObjectReference entity, VMware.Vim.Permission[] permission)
I noticed the System.void. Does that mean it is no longer a valid method in Posh v2 / PowerCLI 4.0 U1 build 208462? If so do I need to run on Posh v1? or is there a workaround.
Thanks for the script and advanced thanks for any assistance.
Terry
Post a Comment