Re-associating vCloud Director VMs with the correct resource pool

Our team was upgrading ESXi hosts in our vCloud Director environment and all of the VMs must have not have migrated when placing the hosts into maintenance mode so they manually migrated the VMs.  Since we have multiple org vDCs, we have multiple resource pools.  As you may know, when you try to migrate VMs that are in multiple resource pools, the migration wizard only allows you to place the VMs in a single resource pool.  I started seeing the following system alert on all of the vCloud Director VMs:

2015-01-15_20-52-07

I checked vCenter and sure enough all of the VMs were in the root resource pool (the cluster), and no longer in the correct resource pool.  If you migrate the VMs one at a time, the migration wizard automatically places the VM in the correct resource pool, but the team didn’t want to do this as it would take too much time.  If you do have to migrate the VMs manually, you can migrate VMs in bulk and have the migration wizard place the VMs in the correct resource pool if you use the following process:

  1. Select a resource pool.
  2. Select the Related Objects tab.
  3. Select Virtual Machines.
  4. Select all of the Virtual Machines.
  5. Select Migrate.

2015-01-15_21-03-23

Here you can see that the wizard automatically selected the correct resource pool:

2015-01-15_21-03-50

You still have to go through each resource pool and perform the migrations, but the VMs will retain the correct resource pool.  Of course, you could script it all as well.

So I was in the position of having all of the VMs in the wrong resource pool, which causes alarms in vCloud Director and could impact the performance of the virtual machines.  I could have went into vCloud Director and found each of the VMs individually, but this would have taken forever so I decided to use PowerCLI to re-associate the VMs with the correct resource pool.

You’ll need to be connected to vCloud and all of your vCenter instances:

connect-ciserver cloud.corp.local

connect-viserver vc.corp.local

Paste the following function into PowerCLI:


function reassociatevCDRPs {
  <#
  .SYNOPSIS
    Places vCloud Director virtual machines into the correct vCenter resource pools.  
  .DESCRIPTION
    Places vCloud Director virtual machines into the correct vCenter resource pools.  This can be helpful when the VMs are moved from their resource pool during a task such as manual vMotion. 
  .EXAMPLE
  reassociatevCDRPs -org all -promptOnMove $false
  .EXAMPLE
  reassociatevCDRPs -org admin -promptOnMove $true
  #>

  param(
    [Parameter(Mandatory=$true)] 
    [string] $org = "all",
    [Parameter(Mandatory=$true)] 
    [string] $promptOnMove = $false
  )

    $ovdcLookupTable = @{}
    $vmsToMove       = @{}

    # Build lookup tables
    $orgIds = @{}
    $orgNames = @{}
    search-cloud -querytype organization | % { $orgIds[$_.name] = $_.id; $orgNames[$_.id] = $_.name }

    $orgVdcIds       = @{}
    $orgVdcNames     = @{}
    search-cloud -querytype AdminOrgVdc | % { $orgVdcNames[$_.id] = $_.name; $orgvDCIds[$_.name] = $_.id }

    $vCDVMs = search-cloud -querytype adminvm

  $searchCommand = "search-cloud -querytype adminvm"

  if ($org -ne 'all') {
    # Throw an error if the organization is not found in the vCloud instance.  Otherwise add a filter to the search-cloud command to only work on the supplied organization.
    if (! $orgIds[$org]) { throw "Organization $org not found." }  
    $searchCommand += " -filter org==$($orgIds[$org])"
  }

  $vcdVMs = invoke-expression $searchCommand

    $vcdVMs | % { 
      $vcdVM = $_
      
      # Get the resouce pool name in the format of: orgVDC Name (UUID)
      $vcdRPName = "$($orgVdcNames[$vcdVM.Vdc]) ($($_.Vdc.split(':')[3]))" 

      $vcVM = get-vm -id "VirtualMachine-$($vcdVM.moref)"
      $vcRP = $vcVM.resourcepool 
      $vcRPName = $vcRP.name
      
      if ($vcdRPName -ne $vcRPName) {  # Test to see if vCD's resource pool matches vCenter's resource pool. 
        echo "$($vcdVM.name) is in the resource pool '$($vcRPName)' and should be the '$($vcdRPName)' resource pool."
        # Add to list of VMs that need to be moved.   
        $vmsToMove[$vcVM] = get-resourcepool $vcdRPName
      }

    }

    $vmsToMove.keys | % { 
      if ($promptOnMove -eq $true) {
        $response = read-host "Move $($_.name) to the correct resource pool ($($vmsToMove[$_])) ( [y]es, [n]o, [a]ll )?"
        if ($response -eq 'n') { # If the user selects not to move the VM, try the next VM in the list.
          return 
        } 
        elseif ($response -eq 'a') {
          $promptOnMove = $false
        } 
      }
      $resourcePool = $vmsToMove[$_] 
      echo "Moving $vm into resource pool $resourcePool"
      move-vm $_ -Destination $resourcePool | out-null
      #echo "result: $($?)"
    }

}

To correct all VMs with no prompting:

reassociatevCDRPs -org all -promptOnMove $false

To move VMs to a specific org and to prompt before each move:

reassociatevCDRPs -org “org name” -promptOnMove $true

This script won’t move shadow VMs, but those are easy… for each cluster just select them all and drag them into the cluster’s System vDC (uuid) resouce pool.  vShield Edges also won’t be moved.  Those will likely need to be moved into the System vDC resource pool as well or if they are a fenced vApp, they will go into an org vDC resource pool.  Or you can just de-deploy them and they should go to the correct resource pool.

Advertisements


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s