Using CloudClient to bulk change vRA Reservations
What happens when you have ~500 VMs in vRealize Automation that need to have their reservations changed? You figure out a way to script that tedious process. (This will provide some background and more details on a recent VMware Communities post.)
I first started looking at what I was most familiar with - PowervRA - a great community supported, PowerShell wrapper for the vRA API stack. Unfortunately, PowervRA does not offer reservation manipulation - only reporting.
CloudClient is a Java application wrapper for the vRA API. Bulk changing reservations is one use case, but several other uses exist in the documentation from that download site.
To use CloudClient in a wrapper script, we must first save our password by interactively launching CloudClient and executing the login keyfile
command. This command specifies an output location for the encrypted file and prompts for a password. Most CloudClient activities require authentication with both vRA and vRA’s IaaS component.
With the files saved, I can then create a CloudConfig.properties file
# CloudClient.Properties File used to automatically login to CloudClient and it should be located in the same directory as lib and bin folders. | |
# Passwords can be provided or simply encrypted to a file, use command: | |
# login keyfile --file mypass.txt --password mypaasword | |
#vra_server : vRealize Automation Virtual Appliance | |
vra_server=vra-server.mycorp.local | |
#vra_tenant : Tenant Name, defaults to vsphere.local | |
vra_tenant=mytenant | |
#vra_username : Username | |
vra_username=pezhore | |
#vra_password : Password | |
#vra_password= | |
#vra_keyfile : Encrypted file location of password | |
vra_keyfile=vra_login.enc | |
# Some Administrator level API calls require Windows Authentication to communicate to the vCAC Infrastructure Service Components | |
#vra_iaas_server : Infrastructure Server (Windows Authentication) where IaaS Web Server node (Model Manager Web) is running, defaults to finding the name dynamically from vCAC | |
vra_iaas_server=vra-web.mycorp.local | |
#vra_iaas_username : Windows username in the form user@domain | |
vra_iaas_username=vra_iaas@mycorp.local | |
#vra_iaas_password : Windows password | |
#vra_iaas_password= | |
#vra_iaas_keyfile : Encrypted file location of Windows password | |
vra_iaas_keyfile=iaas_login.enc |
With the CloudConfig.properties file in place at the same level as the ./bin
folder, I can execute my commands directly from PowerShell
.\bin\cloudclient.sh vra machines change reservation --ids "restest01" --reservationName "Windows\ -\ 02"
This works great for single VMs, but for migrating several hundred - and ensuring the VMs you’re requesting are indeed on the wrong reservation takes a bit more effort. If I connect to vRA with PowervRA, I can gather a list of VMs on the “old” reservation and pass that list of applicable servers to the CloudClient command line. Alternatively, if I provide a list of VMs to PowerShell, I can validate which are on the old reservation and update only those.
The final source can be found below:
<# | |
.SYNOPSIS | |
Script that changes vRA managed machine reservations. | |
.DESCRIPTION | |
Leveraging an existing connection to vRA and a pre-configured cloudclient installation, | |
find all managed machines on a given OldReservation and attempt to change them to a | |
given NewReservation. | |
.EXAMPLE | |
PS C:\> Set-vRAMachineReservation.ps1 | |
Uses defaults to change all machines on the "Windows - 01" reservation | |
to the "Windows - 02" reservation | |
.EXAMPLE | |
PS C:\> Set-vRAMachineReservation.ps1 -OldReservation "Res - 01" -NewReservation "Res - 02" | |
Finds all vRA machines on the "Res - 01" reservation and changes them to the | |
"Res - 02" Reservation | |
.EXAMPLE | |
PS C:\> Set-vRAMachineReservation.ps1 -TargetVMs "Test01","Test02","Test03" | |
Attempts to find the three test VMs in vRA, and if they are a member of the default OldReservation, | |
"Windows - 01", will attempt to change their reservation to the default NewReservation, | |
"Windows - 02" | |
.EXAMPLE | |
PS C:\> Set-vRAMachineReservation.ps1 -TargetVMs "Test01" -OldReservation "Res - 01" | |
Attempts to find the Test01 VM in vRA, and if it is a member of the "Res - 01" reservation, will | |
attempt to change its reservation to the default NewReservation, "Windows - 02" | |
.PARAMETER OldReservation | |
The existing reservation that should be changed | |
.PARAMETER NewReservation | |
The new reservation for all machines found on existing | |
.PARAMETER TargetVMs | |
An array of VM names to target for reservation changes | |
#> | |
[CmdletBinding()] | |
param( | |
[System.String] $OldReservation = "Windows - 01", | |
[System.String] $NewReservation = "Windows - 02", | |
[ValidateScript( { | |
Test-Path -Path $_ -Type Container | |
})] | |
[System.String] $CloudClientPath = "C:\temp\cloudclient\4.4.0\VMware_vRealize_CloudClient-4.4.0-5511232", | |
[System.String[]] $TargetVMs | |
) | |
process { | |
# CloudClient doesn't like spaces. We need to escape them | |
$NewReservation = $NewReservation -replace " ", "\ " | |
# Initialize Values | |
$AllResources = @() | |
$Page = 1 | |
# If we're not asking for a specific set of VMs, grab everything. | |
if (! $TargetVMs) { | |
<# | |
vRA uses pagnation to restrict how many results are returned. It will return *at most* 100 | |
results for a given "page". To fully get all resources, we must leverage a $Count variable | |
to track how many results we have and increment the page for every time we get back 100 | |
results. | |
#> | |
do { | |
# Write out some progress | |
$ProgressSplat = @{ | |
Activity = "Analyzing Resources" | |
Status = "Current page $Page" | |
} | |
Write-Progress @ProgressSplat | |
# Get the vRA Resources (e.g. Machines) for this page. WithExtendedData includes the current | |
# reservation | |
$Group = Get-vRAResource -Page $Page -WithExtendedData | |
# Grab the count of how many objects were retrieved | |
$Count = $Group.count | |
# Increment our page counter | |
$Page ++ | |
# Add this group to the larger AllResources array | |
$AllResources += $Group | |
} while ($Count -ge 100) | |
} | |
else { | |
# Loop through every individual vm in the TargetVMs list | |
foreach ($TargetVM in $TargetVMs) { | |
$AllResources += Get-vRAResource -Name $TargetVM | |
} | |
} | |
# Initialize our list of machines | |
$List = @() | |
# Parse every resource we retrieved above | |
foreach ($Resource in $AllResources) { | |
# If this resource's reservation matches the old reservation, add it to the list | |
if ($Resource.data.machinereservationname -match $OldReservation) { | |
Write-Information -MessageData "$OldReservation participant: $($Resource.name)" -InformationAction Continue | |
$List += $Resource.name | |
} | |
} | |
# CloudClient needs the MachineIDs as a comma separated list | |
$MachineIDs = $List -join "," | |
# Call the cloudclient executable, passing in the MachineIDs and New Reservation | |
$CloudClientBat = Join-Path -Path $CloudClientPath -ChildPath "\bin\cloudclient.bat" | |
& $CloudClientBat vra machines change reservation --ids $MachineIDs --reservationName $NewReservation | |
} |