Platform9 Blog

Automating VMware Tenant Placement in Platform9 OpenStack

One of the reasons customers choose Platform9 as their cloud management platform is because it easily integrates with existing virtualized environments. Customers find great value in the ability to take their current VMware vSphere and/or KVM environment and transform them into a self-service private cloud – without having to create a separate silo or provision new and expensive hardware infrastructure. Instead, they can enable Platform9 Managed OpenStack and allow it to discover their existing infrastructure and workloads. You can read more about why we think this is an important capability and watch a video on how we accomplish it.

That said, one of the constraints we have to work around is that every OpenStack resource must be part of a tenant (also called a project). This is not an issue for other OpenStack solutions since they assume that all resources – including virtual machine instances, networks, and storage volumes – are only created through OpenStack. However, this design assumption becomes an “issue” for Platform9 since we are able to import existing resources such as virtual machines previously created using KVM or VMware vCenter.

Our workaround:  in Platform9, an instance is created initially with a service tenant. A service tenant is a default tenant construct, accessible only to the cloud administrator and anyone to whom they give access. When the Platform9 host agent for KVM or the Platform9 vSphere Gateway performs its periodic discovery tasks, any newly discovered resources are automatically placed into the service tenant. These discovered resources are always the ones created without using Platform9 OpenStack; resources that have been provisioned through the controller itself are already known to the system. Once the resources are in the service tenant, the cloud admin can then move them to other appropriately created tenants.

Platform9 Service Tenant

While this workaround is necessary for Platform9 to enable discovery of existing environments, it can be a challenge for customers with hundreds or thousands of existing VMs, which would need to be moved manually to the appropriate tenants after discovery. One such Platform9 customer asked us to help find an easy way to organize their Platform9 managed virtual machines using their current vCenter folder structure, i.e. map OpenStack tenants to vCenter folders and then automatically move VMs from the service tenant to the tenant with a name that maps to their corresponding folder name in vCenter.

To accomplish this, I created a PowerShell script that will query the service tenant for discovered VMs, search for those VMs in vCenter and get their folder structure. If a VM is in a folder that matches a tenant name, the script will execute a command to move that VM to its corresponding Platform9 OpenStack tenant. You can find the PowerShell script below:

# Include a cool function that makes finding the full path of a VM easy. (Thanks Grzegorz Kulikowski -
. .Get-VMFolderPath.ps1

# What Tenant do you want to work with? (This should be the "service" tenant for Platform9 administration)
$osTenant = "service"
# What User do you want to authenticate as? (This user MUST be an admin on ALL tenants in order to reassign VM ownership to all tenants)
$osUsername = ""
# What is the above user's Password?
$osPassword = "YourPassWordHere"
# What is your Identity API Endpoint? (This can be found on the API Access tab of the Access and Security section in the Platform9 Clarity UI)
$osIdentityEndpoint = ""
# What is your Compute API Endpoint? (This can be found on the API Access tab of the Access and Security section in the Platform9 Clarity UI)
$apiComputeEndpoint = ""

# What is your vCenter FQDN?
$vcServer = "FQDNofYourvCenter"
# What is your vCenter Username?
$vcUsername = "vCenterAdminPassword"
# What is your vCenter Password?
$vcPassword = "YourvCenterPassword"

# Create the authentication JSON for the Identity API
$authJSON = '{"auth": {"tenantName": "' + $osTenant + '","passwordCredentials": {"username": "' + $osUsername + '","password": "' + $osPassword + '"}}}' # Fix Syntax Highlighting bug by adding this --> '

# Call the Identity API to autenticate and retrive a token to be used for future API calls
$authResult = Invoke-RestMethod -Method Post -Uri "$osIdentityEndpointtokens" -Body ($authJSON) -ContentType 'application/json' -Headers @{'Accept'='application/json'}
# Pull the X-Auth-Token from the authResult
$osToken = $
# Pull the User ID from the authResult
$osUserId = $

# Call the Identity API using the token retrived above and get a list of all Tenants you have access to
$tenantResult = Invoke-RestMethod -Method Get -Uri "$osIdentityEndpointtenants" -Headers @{'X-Auth-Token'=$osToken}
# Pull the array of tenants from the tenantResult
$osTenants = $tenantResult.tenants

# Call the Compute API using the token retrived above and get a list of all servers in your tenant
$serverResult = Invoke-RestMethod -Method Get -Uri "$apiComputeEndpointservers" -Headers @{'X-Auth-Token'=$osToken}
# Pull the array of servers from the serverResult
$osServers = $serverResult.servers

# Connect to vCenter using the credentials provided above.
Connect-VIServer -Server $vcServer -User $vcUsername -Password $vcPassword

# Loop through each Server
ForEach($server in $osServers) {
#Make all errors terminating
$ErrorActionPreference = "Stop"
# Find the VM Folder Path in vCenter of the OpenStack server instance
$vmPath = Get-VM -Name $ | Get-VMFolderPath
# If we are in this block of code either the VM could not be found, or we couldn't determine which folder the VM is in.
$ + ": Could not be found in vCenter (Has it been deleted?)"
$vmPath = "vmNotFound"
#Reset the error action pref to default
$ErrorActionPreference = "Continue"

If($vmPath -ne "vmNotFound"){
#Make all errors terminating
$ErrorActionPreference = "Stop"
# Split the folder path and grab the third folder in the path (We're assuming this is the "Tenant Name")
$tenantFolder = $vmPath.Split("")[2]
# If we are in this block of code the VM is either in the root of the Inventory, or something is wrong with the folder structure.
"VM " + $ + " is in folder " + $vmPath + " which seems to be the root VM folder, or something else went wrong."
$tenantFolder = "folderNotFound"
#Reset the error action pref to default
$ErrorActionPreference = "Continue"

# Make sure the folder name isn't blank
If ((!$tenantFolder) -And ($tenantFolder -ne "folderNotFound")){
# Loop through each Tenant
ForEach ($tenant in $osTenants){
# See if the tenant name matches the tenantFolder
If ($ -eq $tenantFolder){
# Move the VM from the service tenant to their folderTenant and change the owner to the user that is running this script.
$ChangeOwner = Invoke-RestMethod -Method Post -Uri ($apiComputeEndpoint + 'servers' + $ + 'action') -Body ('{"changeOwner":{"tenant":"' + $ + '","user":"' + $osUserId + '"}}') -ContentType 'application/json' -Headers @{'X-Auth-Token'=$osToken}
# Disconnect for the vCenter Server
Disconnect-VIServer -Confirm:$False

So what’s next? What if you find a VM inside of a vCenter folder and that folder name doesn’t already exist as a Platform9 OpenStack tenant? Well, you could use a script to create that tenant on the fly and then move that VM to that tenant. To take it a step further, if you have already delegated permissions to that folder to certain users in vCenter, you could assign those users access to that new tenant in Platform9 as well.

Stayed tuned for more. And let me know if you found this PowerShell script useful.

Cody Hill
Cody Hill works as a Cloud Architect at Platform9. You can follow him on Twitter @EyeOnTheCloud.

The browser you are using is outdated. For the best experience please download or update your browser to one of the following: