Zero2Hero - Using Aria Automation to Deploy Multiple Machines with Multiple Disks - Part 3



VMware Aria VMware Aria Automation

Published on 6 March 2024 by Christopher Lewis. Words: 1717. Reading Time: 9 mins.

In part three of this five post blog series, we will continue our #Zero2Hero journey in understanding the authoring VMware Cloud Templates. We will continue with working towards the use case for deploy multiple virtual machines (with additional on-demand disk configurations).

The series will cover the following high level use cases:

  • Creating a Single Virtual Machine Cloud Template (boot disk only) - Part 1
  • Creating a Single Virtual Machine Cloud Template (with additional static disk configuration) - Part 2
  • Creating a Multiple Virtual Machine Cloud Template (with additional static disk configuration) - Part 3
  • Creating a Single Virtual Machine Cloud Template (with additional on-demand disk configurations) - Part 4
  • Creating a Multiple Virtual Machine Cloud Template (with additional on-demand disk configurations) - Part 5


The Requirements (Recap)

As a reminder we had the following high level requirements when developing this cloud template:

  1. The consumer must be able to deploy one or more Virtual Machines.
  2. The consumer must be able to choose the operating system (image) for the Virtual Machine.
  3. The consumer must be able to choose the Virtual Machine size (flavor) at request time.
  4. The consumer Must be able to choose to which cloud the Virtual Machine is deployed to (i.e. VMware Cloud or Private Cloud)
  5. Each Virtual Machine must have identical disk configuration.
  6. The disk configuration must support one to five additional disks.
  7. The disk configuration must be chosen at request time.

The Development Process

Now we are starting to look at deploying multiple resources from a single VMware Cloud Template, it is important to understand the difference between multiple resources and clustered resources.

There are really only two options for deploying more than one resources within a VMware Cloud Template:

  1. Add more than one identically configured, individual Resource objects to the canvas.
  2. Add the count property to single resource object, thus creating a Clustered Resource object.

We use the term Clustered Resource because using the count property to determine the number of resources of a particular type (such as Virtual Machines) is effectively creating a cluster of identically configured resources.

Both options have their advantages and disadvantages. For example, adding more resource objects may mean addition inputs which maybe be difficult more difficult maintain but provides ultimate flexibility when filling out those inputs, where as using the count property can increase the complexity of the YAML code being used within the cloud template, but will simplify the number of inputs (but will also restrict the flexibility) of each resource type.

Creating Multiple Virtual Machines (with additional static disk configuration)

Inputs

To continue to build out our use case, we are going introduce a new input into the VMware Cloud Template:

  • numVms - This is going to be the number of Virtual Machines we would like to deploy.

Resources

Using the an updated scenario, we have requested 2 Virtual Machines and each Virtual Machine has 2 disks. So now let us explore what happens in the VMware Cloud Template.

Cloud.vSphere.Machine

As discussed above, we are going introduce a new property into the Cloud.vSphere.Machine resource object:

  • count - This is the number of Cloud.vSphere.Machine resource objects in the resource array or the value of the numVms input and then VMware Aria Automation knows to deploy X number of Virtual Machines..

However, we cannot just add the count property into the Cloud.vSphere.Machine object because you will get a Shared Disk is not supported error when you try to deploy multiple machines.

Therefore, we are also going to introduce a new Resource Flag:

  • allocatePerInstance - This is used so that VMware Aria Automation know to allow resource allocation to be customized for each object rather than once for all objects.


It would be remiss of me not to highlight the changes we would have to make manually to the attachedDisks property in the Cloud.vSphere.Machine to support this type of multi-disk configuration.

As we can see this is no longer a YAML array of disk resource ids but some sort of formula/expression that looks like it belongs in a spreadsheet.

attachedDisks: ${map_to_object(slice(resource.disk1[*].id, count.index, count.index+1), "source") 
  + map_to_object(slice(resource.disk2[*].id, count.index, count.index+1), "source")}

Let us try and break that down (with an example) to make it easier to understand and, hopefully, re-use the logic for other templates.

Using the same scenario as above, we have requested 2 Virtual Machines and we know that each Virtual Machine has 2 static disks. So now let us explore the expression and what happens.

  • count is the number of elements in the Cloud.vSphere.Machine resource array. As this is 2, we have vm[0] and vm[1].
  • count.index is the position of the current Virtual Machine in the resource array. As we iterate through the array, this will be 0 and then 1.
  • count.index+1 is just pure maths as we add 1 to the index of the array. As we iterate through the array, this will be 1 and then 2.
  • resource.disk1[*] - is an array of Cloud.vSphere.Disks objects. As we have 2 disks, then there will be two elements in this array, i.e. resource.disk1[0] and resource.disk1[1].
  • resource.disk1[*].id is an array of the id’s for the disk1 resource object. As we have 2 disks, then there will be two resource id’s in this array, i.e. resource.disk1[0].id and resource.disk1[1].id.
  • slice(resource.disk1[*].id, count.index, count.index+1) - As we iterate through each of the Cloud.vSphere.Machine objects in the resource array, this is used to return a specific subset (or slice) of the resource array. This translates to:
  • On the first iteration through (for vm[0]), return an array containing a single element between index 0 and 1, i.e. resource.disk1[0].id.
  • On the second iteration through (for vm[1])), return an array containing a single element between index 1 and index 2, i.e. resource.disk1[1].id.
  • map_to_object(slice(resource.disk1[*].id, count.index, count.index+1), "source") returns the elements of the sliced resource.disk1[*].id array to the attachedDisks property using the key field called source.
  • map_to_object(slice(resource.disk2[*].id, count.index, count.index+1), "source") does the same as above, but for the resource.disk2[*] array.
  • The + just creates a list of the results from the two expression.

So if we could visualize the expanded expression syntax to see what the YAML would actually look like, we would see:

For vm[0], the first element in the resource array, this expands to:

  vm[0]:
    type: Cloud.vSphere.Machine
    properties:
      image: windows
      flavor: small
      constraints:
        - tag: cloud:vmc
      attachedDisks:
        - source: ${resource.disk1[0].id}
        - source: ${resource.disk2[0].id}

For vm[1], the second element in the resource array, this expands to:

  vm[1]:
    type: Cloud.vSphere.Machine
    properties:
      image: windows
      flavor: small
      constraints:
        - tag: cloud:vmc
      attachedDisks:
        - source: ${resource.disk1[1].id}
        - source: ${resource.disk2[1].id}


Cloud.vSphere.Disk

We also going introduce a new property into the Cloud.vSphere.Disk resource object:

  • count - This is the number of Cloud.vSphere.Disk resource objects in each resource array.

So let us think about this logically:

  • Each Virtual Machine has two separate disks (named disk1 and disk2) configured.
  • If X is the number of Virtual Machines being deployed, and instances of disk1 and disk2 need to be attached to each Virtual Machine, then we need X times disk1 and X times disk2 to also be deployed so we have enough disks.
  • This means if X = 2, then the number of disk1 = 2 and the number of disk2 = 2

We also need to introduce a new Resource Flag for the Cloud.vSphere.Disk object:

  • allocatePerInstance - This is used so that VMware Aria Automation know to allow resource allocation to be customized for each object rather than once for all objects.

For more detailed information on Expression Syntax, checkout VMware Aria Automation Assembler Expression Syntax on the VMware Documentation site.

Template Code

Adding that all together and we get the following VMware Cloud Template YAML code:


Wrapping It All Up

In this third post of the series we have gone into a lot more detail to the changes made to the VMware Cloud Template to add additional functionality. We covered what happens when you deploy multiple resource objects in an array (using the count property) rather than as separate resources. We also covered how we can configure VMware Aria Automation to run any configuration tasks on a per resource rather than all resource basis(allocatePerInstance).

Looking back at the requirements we had for this series of articles, we essentially have now crossed off #1, #2, #3, #4 and #5.

It is worth noting the warning above around the Cloud Template we have created. Whilst a dynamic Multi-VM, static Multi-Disk cloud template may sound awesome, it does come with restrictions that may mean we need to find a better way.

In the fourth part of the series, we will look at how we can create on-demand disk configuration with a single machine deployment, before (in part 5) working towards our final VMware Cloud Template.

Published on 6 March 2024 by Christopher Lewis. Words: 1717. Reading Time: 9 mins.