VMware Cloud Community
KAhnemann
Contributor
Contributor

VRA 8.1 - Placement policies based on username and tags

Running version 8.1

I've been trying to find a way to customize my blueprint so it pulls the username (without the @domain.com suffix) and uses constraint tags to place the VM on the right network, in the right resource pool, and in the right folder.  All of these items have tags that match a username in AD that was all created with a script.  If I manually enter the username as the constraint tag, it works great.  I need it to happen dynamically though. 

I was using the ${env.requestedBy}' variable, but it adds the @domain.com to the username.  It's not a huge deal, but the VM folder matches the username, and not the entire name with @domain.com. 

Also, the VM folder is a sub folder (Lab VMs\Username) and it doesn't seem to like to mix a variable with a folder structure.  It ends up creating a folder like "Lab VMS%5Username" or something.   I may just be messing up the syntax on that last line when I try and add "Lab VMs\ before the variable.

I wish there was a way to place the VM in a folder based on tags like resource pools...  Maybe this can be accomplished with a extensibility action and a powershell script?

Also, is there a way to make YAML not case sensitive when looking at tags? lol

formatVersion: 1

inputs:

  VMName:

    type: string

    title: Server Name

  SelectFlavor:

    type: string

    enum:

      - Small - 2cpu x 4gb

      - Medium - 4cpu x 8gb

      - Large - 8cpu x 12gb

    description: ''

    default: Small - 2cpu x 4gb

    title: Select VM Size

resources:

  Cloud_Network_1:

    type: Cloud.NSX.Network

    properties:

      networkType: existing

      constraints:

        - tag: '${env.requestedBy}'

  Cloud_vSphere_Machine_1:

    type: Cloud.vSphere.Machine

    properties:

      userDefinedName: '${input.VMName}'

      flavor: '${input.SelectFlavor}'

      image: Server 2019

      customizationSpec: Server 2019

      constraints:

        - tag: 'ResourcePools:${env.requestedBy}'

      networks:

        - network: '${resource.Cloud_Network_1.id}'

      folderName: '${env.requestedBy}'

Thanks!

8 Replies
dbis7575
Enthusiast
Enthusiast

See the following link: Cloud Assembly blueprint expression syntax

If you want to use a "\" in a string you will have to escape it with "\\" (i.e. "lab\\folder"

There are some build in functions that can be used in the cloud-assembly yaml. If you wanted to strip the "@domain.com" the obvious way would be to use the substring function, but I couldnt get this to work when the end index was a function (i.e. ${substring(env.requestedBy), 0, (length(env.requestedBy) - 11)}), but using the replace function it does work:

${replace(env.requestedBy, "@domain.com", "")}'

Note that there is basic if, then functionality in the cloud assembly yaml but this doesnt work if you nest it. You also cant define a variable and then call it again within your yaml code, as these wouldn't be processed until the allocation phase. This means if you have one or two domains you have to strip you can make it work, but anything more you are looking at adding an action/workflow.

Yaml is case sensitive when it comes to tags, but you could define all your tags as lower case and any variable you use you could use the to_lower() function.

KAhnemann
Contributor
Contributor

Still not sure how to get the \\ to work with this.

Code is

folderName: 'Lab VMs\\${replace(env.requestedBy, "@Domain.com", "")}'

What gets created

Lab VMs%5c%5cUser@Domain.com.

Also, for tag constraints, is this what you had in mind?

  Cloud_Network_1:

    type: Cloud.NSX.Network

    properties:

      networkType: existing

      constraints:

        - tag: '${replace(env.requestedBy, "@Domain.com", "")}'

Reply
0 Kudos
dbis7575
Enthusiast
Enthusiast

You would have to concatonate the strings, havent tested it but it should look something like:

folderName: '${"Lab VMs\\" + replace(env.requestedBy, "@Domain.com", "")}

As far as your tag, it is going to have to be in KEY:VALUE format, you are just pushing the username as a string into it. I assume this is your value, so you will have to add the key to it as well.

dbis7575
Enthusiast
Enthusiast

You would have to concatonate the strings, havent tested it but it should look something like:

folderName: '${"Lab VMs\\" + replace(env.requestedBy, "@Domain.com", "")}

As far as your tag, it is going to have to be in KEY:VALUE format, you are just pushing the username as a string into it. I assume this is your value, so you will have to add the key to it as well. You would create this using the same syntax as used for the foldername

KAhnemann
Contributor
Contributor

Thanks for the help!

I'm new to this, so I need to figure out what you mean on the key value format.  I found this in the guide, but not sure how to wrap it all together into the blueprint to pass into the folder name as well as the constraint tags.  Tags are usernames, that is correct.  So for example, a resource pool has a tag of TUser or a network has a tag of TUser. 

tags:
  - key: cas.requestedBy
    value: '${env.requestedBy}'

Reply
0 Kudos
dbis7575
Enthusiast
Enthusiast

Tags are just constructs that are typically used for informational purposes and you can define any key:value pairs you want. This way you can report on it, but with Cloud assembly you can use them as constraints as well. You do have to associate tags with objects before you can use them as constrains within your blueprint.

So for example, if you want to use a constraint on a network resource you would associate a tag with a network profile or even a network within a network profile. Then within your blueprint you would use that tag as a constraint. Let's say you have two networks, one of them you assign a tag "Network:Production" and the other one a tag "Network:Development" you can use these in your blueprint to ensure a specific network is used. An example is listed below:

constraints:

        - tag: '${input.Environment == "PROD" ? "Network:Production" : "Network:Development"}'

This would look at an input field called Environment, if the input matches "PROD" it sets the tag to Network:Production and otherwise to Network:Development

KAhnemann
Contributor
Contributor

I think I'm good on understanding that part.

I have network tagged with TDelete(the username) and this works fine when the code is like this

  Cloud_Network_1:

    type: Cloud.NSX.Network

    properties:

      networkType: existing

      constraints:

        - tag: 'TDelete'

My issue is trying to convert that last line to a variable that pulls the username of the person using VRA, removing the @domain.com from the end, and passing it through as the value for the tag.

Replacing TDelete with '${replace(env.requestedBy, "@domain.com", "")}' doesn't seem to actually remove the @domain.com

Is there a way to define a variable higher up in the blueprint and then just call it for this value?  Example $ADUsername = '${replace(env.requestedBy, "@accudatalab.com", "")}' 

I use PowerShell, so that's why I gave that as an example.

Thanks for your time!

Reply
0 Kudos
dbis7575
Enthusiast
Enthusiast

We can't define a variable and then reference it again within the same yaml blueprint. If you do, you will just see your variable name listed instead of the value.

I am able to use this in my test environment and it works fine, but a tag should be in key"value format.

So lets say your key is named VLAN and your value is the username, the tag would be in the format of VLAN:username. Off course you can use any key name.

example:

- tag: '${"VLAN:" + replace(env.requestedBy, "@domain.com", "")}'

Reply
0 Kudos