Using ABX to change DNS Servers for a vRA Deployment at provisioning time

Hello Everyone,

On today’s post, we will go through creating an ABX Action to change the DNS Servers for a Deployment in vRA8. This might be needed to do in scenarios in which, even though the network has DNS servers configured, a specific deployment might require to use other DNS Servers while still being on the same network, for example, to join a different AD domain

The same idea can be used to edit other fields of the deployment, such as the IP Address, search domains, etc.

The post will be divided in 5 sections:

  • Cloud Template
  • Event Topic
  • ABX Action
  • ABX Subscription
  • Test

Cloud Template

In the template we’re going to need two inputs – dnsServers (comma separated list of DNS Servers) as well as an input to manage the amount of VMs in the deployment, we can call it ‘instances’

 instances:
    type: integer
    title: Amount of VMs
    default: 1
    maximum: 5
  dnsServers:
    type: string
    description: Comma separated list of DNS Servers
    title: DNS Servers
    default: '1.1.1.1,8.8.8.8'

These two values will be custom properties on the VM Object

properties:
   count: '${input.instances}'
   dnsServers: '${input.dnsServers}'

In addition to this, the network assignment for the VM resource should be set to ‘static’. A customization specification profile is optional, since using a ‘static’ assignment will auto-generate a ‘ghost’ customization specification profile at the time of provisioning

networks:
    - network: '${resource.VMNetwork1.id}'
      assignment: static

Event Topic

The event topic that we need to use to make changes to the Network Configuration is the one that has the object that we need to edit being presented to the workflow in an editable state, as in, not read-only.

For this specific use, the state is Network Configure

Pay special attention to the ‘Fired once for a cluster of machines’ part

The dnsServers object is a 3D Array, so that is what we need to use in the ABX Action Code

So from this point we learn that:

  • The action will run once for a cluster of machines, so if we were to do a Multi-VM deployment we need to take this into account, otherwise, it will only run for a single VM and not all of the VMs in the deployment
  • a 3D array needs to be used to insert the DNS Servers into the object at the event topic

ABX Action

For this example, I will use Python, and I will not use any external libraries for array management (such as numpy) since I wanted to see if it could be done natively. Python has way better native support for lists than it does for arrays, but in this case, given the schema of the object in the event topic, we’re forced to use a 3D Array.

The first thing we need to do when creating the action, is to add the needed inputs. In this one, I will add the custom properties of the resources as an input

Adding the custom properties

Once we have that as an input, we can use it to get the data we need (amount of instances and DNS servers)

To pass data back to the provisioning state, we will use and return the ‘outputs’ object

This is the code of the action itself, I will explain it below

def handler(context, inputs):
    outputs = {}
    dnsServers = [[[]]]
    instances = inputs["customProperties"]["count"]
    inputDnsServers = inputs["customProperties"]["dnsServers"].split(",")
    if (len(inputDnsServers) > 0):
        outputs["dnsServers"] = dnsServers
        outputs["dnsServers"][0][0] = inputDnsServers
        for i in range(1,int(instances)):
            outputs["dnsServers"] = outputs["dnsServers"] + [[inputDnsServers]]
    return outputs
  • Define the outputs object
  • Define the 3D Array for DNS Servers
  • Assign the inputs as variables in the script
  • Convert the comma separated string into a List
  • If the list is not empty (this means that the user did enter a value in the DNS Servers list on the input form) then we add the 3D Array to the outputs object.
    • Why am I asking to see if it is empty? Because if the user did not put anything on the field, we will be overwriting the output with an empty array, and that will overwrite the DNS that were read from the network in vRA. We only want to overwrite that if we’re actually changing the DNS Servers.
  • Also in the same condition, we want to add the DNS Servers array to each VM, so we iterate through the amount of VMs.
    • The way to add it without using numpy (we have no append method) is not elegant, but it does the trick. Basically, we initialize the first element and then we add other elements to the same array using the same format.
  • Return the outputs object

This can also be done in javascript and powershell, the idea would be the same.

So how does this object look like in an actual run?

In this example, I changed the DNS for 3 VMs – You can see that we’re using the 3D Array Structure

Lastly, we need to configure a subscription for it to run at this specific state.

ABX Subscription

This is the most straightforward part – We create a blocking subscription in the Network Configure state, and we add the action we just created

The ABX subscription can be filtered via a condition (for example, to run only on specific cloud templates) as well.

So let’s do our deployment now!

The network i’m going to select has the 8.8.8.8 DNS configured

This will be overwritten by whatever we put on the input form. I’m going to use 1.2.3.4 and 5.6.7.8 for this example, and there will be 2 VMs in the deployment

We can check the output of the action before the deployment finishes

Action run started by an Event (Subscription)
Action output

In there we can see the actual code that run, if it was successful or not, the payload, and the output the action had. In this case, our two DNS Servers for our two VMs with a successful output.

Checking the DNS for one of the VMs, we can see the two DNS Servers we selected as inputs!

Success!!!

Summary

I hope you found this post useful! The same idea can be used to change several other properties at provisioning time. Also, it was a learning experience for me to learn how to play with arrays in Python natively, and how to interact with ABX properly.

More posts will be coming soon!

If you liked this one, please share it and/or leave a comment!

Leave a comment