vCenter PowerCLI Migration Script

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

#load Vmware Module
Add-PSSnapin VMware.VimAutomation.Core

#Change to multi-mode vcenter management
Set-PowerCLIConfiguration -DefaultVIServerMode Multiple -Confirm:$false

#Get vCenter Server Names
$sourceVI = Read-Host "Please enter the name of the source Server"; 
$destVI = Read-Host "Please enter the name of the destination Server"

$creds = get-credential

$datacenter = Read-Host "Please give the name of the datacenter you would like to run against"

#Connect to Source vCenter
connect-viserver -server $sourceVI -credential $creds
connect-viserver -server $destVI -credential $creds -NotDefault:$false

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
    }
 }

## Export all folders
$report = @()
$report = get-datacenter $datacenter -Server $sourceVI| Get-folder vm | get-folder | Get-Folderpath
        ##Replace the top level with vm
        foreach ($line in $report) {
        $line.Path = ($line.Path).Replace($datacenter + "\","vm\")
        }
$report | Export-Csv "c:\Folders-with-FolderPath-$($datacenter).csv" -NoTypeInformation

##Export all VM locations
$report = @()
$report = get-datacenter $datacenter -Server $sourceVI| get-vm | Get-Folderpath

$report | Export-Csv "c:\vms-with-FolderPath-$($datacenter).csv" -NoTypeInformation

#Get the Permissions  

$folderperms = get-datacenter $datacenter -Server $sourceVI | Get-Folder | Get-VIPermission
$vmperms = Get-Datacenter $datacenter -Server $sourceVI | get-vm | Get-VIPermission

$permissions = get-datacenter $datacenter -Server $sourceVI | Get-VIpermission

        $report = @()
            foreach($perm in $permissions){
               $row = "" | select EntityId, FolderName, Role, Principal, IsGroup, Propagate
               $row.EntityId = $perm.EntityId
               $Foldername = (Get-View -id $perm.EntityId).Name
               $row.FolderName = $foldername
               $row.Principal = $perm.Principal
               $row.Role = $perm.Role
               $row.IsGroup = $perm.IsGroup
               $row.Propagate = $perm.Propagate
               $report += $row
            }

            foreach($perm in $folderperms){
               $row = "" | select EntityId, FolderName, Role, Principal, IsGroup, Propagate
               $row.EntityId = $perm.EntityId
               $Foldername = (Get-View -id $perm.EntityId).Name
               $row.FolderName = $foldername
               $row.Principal = $perm.Principal
               $row.Role = $perm.Role
               $row.IsGroup = $perm.IsGroup
               $row.Propagate = $perm.Propagate
               $report += $row
            }

            foreach($perm in $vmperms){
                $row = "" | select EntityId, FolderName, Role, Principal, IsGroup, Propagate
                $row.EntityId = $perm.EntityId
                $Foldername = (Get-View -id $perm.EntityId).Name
                $row.FolderName = $foldername
                $row.Principal = $perm.Principal
                $row.Role = $perm.Role
                $row.IsGroup = $perm.IsGroup
                $row.Propagate = $perm.Propagate
                $report += $row
            }

        $report | export-csv "c:\perms-$($datacenter).csv" -NoTypeInformation

##Export VM Custom Attributes and notes

$vmlist = get-datacenter $datacenter -Server $sourceVI| get-vm
$Report =@()
    foreach ($vm in $vmlist) {
        $row = "" | Select Name, Notes, Key, Value, Key1, Value1
        $row.name = $vm.Name
        $row.Notes = $vm | select -ExpandProperty Notes
        $customattribs = $vm | select -ExpandProperty CustomFields
        $row.Key = $customattribs[0].Key
        $row.Value = $customattribs[0].value
        $row.Key1 = $customattribs[1].Key
        $row.Value1 = $customattribs[1].value
        $Report += $row
    }

$report | Export-Csv "c:\vms-with-notes-and-attributes-$($datacenter).csv" -NoTypeInformation

##Disconnect-VIServer -Server $sourceVI -force -confirm:$false

#connect to Destination Server
##connect-viserver -server $destVI -credential $creds -confirm:$false

##IMPORT FOLDERS
$vmfolder = Import-Csv "c:\Folders-with-FolderPath-$($datacenter).csv" | Sort-Object -Property Path

foreach($folder in $VMfolder){
    $key = @()
    $key =  ($folder.Path -split "\\")[-2]
    if ($key -eq "vm") {
        get-datacenter $datacenter -Server $destVI | get-folder vm | New-Folder -Name $folder.Name
    } else {
        get-datacenter $datacenter -Server $destVI | get-folder vm | get-folder $key | New-Folder -Name $folder.Name
    }
}

##ESX host migration
#Switch off HA

Get-Cluster $datacenter -Server $sourceVI  | Set-Cluster -HAEnabled:$false -DrsEnabled:$false -Confirm:$false

#Remove ESX hosts from old vcenter
$Myvmhosts = get-datacenter $datacenter -Server $sourceVI | Get-VMHost
foreach ($line in $Myvmhosts) {
    Get-vmhost -Server $sourceVI -Name $line.Name | Set-VMHost -State "Disconnected" -Confirm:$false
    Get-VMHost -server $sourceVI -Name $line.Name | Remove-VMHost -Confirm:$false
}

#add ESX hosts into new vcenter
foreach ($line in $Myvmhosts) {
    Add-VMHost -Name $line.name  -Location (Get-Datacenter $datacenter -server $destVI) -user root -Password trunk@1 -Force
}

#Turn on HA and DRS on
Set-Cluster -Server $destVI Cluster1 -DrsEnabled:$true -HAEnabled:$true -Confirm:$false
Disconnect-VIServer $sourceVI -Confirm:$false

##workaround for non working new-vipermissions
function New-VIAccount($principal) {
    $flags = [System.Reflection.BindingFlags]::NonPublic -bor [System.Reflection.BindingFlags]::Public -bor [System.Reflection.BindingFlags]::DeclaredOnly -bor [System.Reflection.BindingFlags]::Instance
    $method = $defaultviserver.GetType().GetMethods($flags) | where { $_.Name -eq "VMware.VimAutomation.Types.VIObjectCore.get_Client" }
    $client = $method.Invoke($global:DefaultVIServer, $null)
    Write-Output (New-Object VMware.VimAutomation.Client20.PermissionManagement.VCUserAccountImpl -ArgumentList $principal, "", $client)
}

##move the vm's to correct location
$VMfolder = @()
$VMfolder = import-csv "c:\VMs-with-FolderPath-$($datacenter).csv" | Sort-Object -Property Path
foreach($guest in $VMfolder){
    $key = @()
    $key =  Split-Path $guest.Path | split-path -leaf
    Move-VM (get-datacenter $datacenter -Server $destVI  | Get-VM $guest.Name) -Destination (get-datacenter $datacenter -Server $destVI | Get-folder $key)
}

##Import VM Custom Attributes and Notes

$NewAttribs = Import-Csv "C:\vms-with-notes-and-attributes-$($datacenter).csv"
    foreach ($line in $NewAttribs) {
        set-vm -vm $line.Name -Description $line.Notes -Confirm:$false
        Set-CustomField -Entity (get-vm $line.Name) -Name $line.Key -Value $line.Value -confirm:$false
        Set-CustomField -Entity (get-vm $line.Name) -Name $line.Key1 -Value $line.Value1 -confirm:$false
    }

##Import Permissions
$permissions = @()
$permissions = Import-Csv "c:\perms-$($datacenter).csv"

foreach ($perm in $permissions) {
    $entity = ""
    $entity = New-Object VMware.Vim.ManagedObjectReference

    switch -wildcard ($perm.EntityId)
        {
            Folder* {
            $entity.type = "Folder"
            $entity.value = ((get-datacenter $datacenter | get-folder $perm.Foldername).ID).Trimstart("Folder-")
        }
            VirtualMachine* {
            $entity.Type = "VirtualMachine"
            $entity.value = ((get-datacenter $datacenter | Get-vm $perm.Foldername).Id).Trimstart("VirtualMachine-")
        }
}
$setperm = New-Object VMware.Vim.Permission
$setperm.principal = $perm.Principal
    if ($perm.isgroup -eq "True") {
        $setperm.group = $true
    } else {
        $setperm.group = $false
    }
$setperm.roleId = (Get-virole $perm.Role).id
    if ($perm.propagate -eq "True") {
        $setperm.propagate = $true
    } else {
        $setperm.propagate = $false
    }

$doactual = Get-View -Id 'AuthorizationManager-AuthorizationManager'
$doactual.SetEntityPermissions($entity, $setperm)
}

##Error Checking
################

##Gather all info for New vCenter
##Export all folders
$report = @()
$report = Get-folder vm -server $destVI | get-folder | Get-Folderpath
        ##Replace the top level with vm
        foreach ($line in $report) {
            $line.Path = ($line.Path).Replace("DC1\","vm\")
        }
$report | Export-Csv "c:\Folders-with-FolderPath_dest.csv" -NoTypeInformation

##Export all VM locations
$report = @()
$report = get-vm -server $destVI | Get-Folderpath
$report | Export-Csv "c:\vms-with-FolderPath_dest.csv" -NoTypeInformation

#Get the Permissions
$permissions = Get-VIpermission -Server $destVI

    $report = @()
    foreach($perm in $permissions){
        $row = "" | select EntityId, FolderName, Role, Principal, IsGroup, Propopgate
        $row.EntityId = $perm.EntityId
        $Foldername = (Get-View -id $perm.EntityId).Name
        $row.FolderName = $foldername
        $row.Principal = $perm.Principal
        $row.Role = $perm.Role
        $report += $row

        $report | export-csv "c:\perms_dest.csv" -NoTypeInformation

 ##Export VM Custom Attributes and notes

 $vmlist = get-vm -Server $destVI
 $Report =@()
    foreach ($vm in $vmlist) {
        $row = "" | Select Name, Notes, Key, Value, Key1, Value1
        $row.name = $vm.Name
        $row.Notes = $vm | select -ExpandProperty Notes
        $customattribs = $vm | select -ExpandProperty CustomFields
        $row.Key = $customattribs[0].Key
        $row.Value = $customattribs[0].value
        $row.Key1 = $customattribs[1].Key
        $row.Value1 = $customattribs[1].value
        $Report += $row
    }

 $report | Export-Csv "c:\vms-with-notes-and attributes_dest.csv" -NoTypeInformation

##compare the source and destination - this part is not yet finished
write-output "Folder-paths"
Compare-Object -ReferenceObject (import-csv C:\vms-with-FolderPath.csv) (import-csv C:\vms-with-FolderPath_dest.csv) -IncludeEqual

write-output "Notes & Attributes"
Compare-Object -ReferenceObject (import-csv "C:\vms-with-notes-and attributes.csv") (import-csv "C:\vms-with-notes-and attributes_dest.csv") -IncludeEqual

write-output "Permissions"

Compare-Object -ReferenceObject (import-csv C:\perms.csv | select * -ExcludeProperty EntityId) (import-csv C:\perms_dest.csv | select * -ExcludeProperty EntityId) -IncludeEqual

Disconnect-VIServer -Server $destVI -Force -confirm:$false

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

Save