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 $creds
18: 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 = $_.Name
28: do {
29: $parent = $current
30: 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.EntityId
65: $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.EntityId
77: $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 $vmerms){
87: $row = "" | select EntityId, FolderName, Role, Principal, IsGroup, Propagate
88: $row.EntityId = $perm.EntityId
89: $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.Name
107: $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 FOLDERS
127: $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 HA
142: Get-Cluster $datacenter -Server $sourceVI | Set-Cluster -HAEnabled:$false -DrsEnabled:$false -Confirm:$false
143:
144: #Remove ESX hosts from old vcenter
145: $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 -leaf
176: 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.Principal
212: 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.EntityId
255: $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.Name
270: $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
17 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 ?
Post a Comment