jselover16
Contributor
Contributor

vRA 8.4 - Cloud Template Nested Arrays and Dynamic Networking

Hey Everyone,

My goal is to build a dynamic cloud template that I can use for a base template for onboarding. I have a few thousand machines to onboard and I want to onboard them in one cloud template that could be matched with just about every configuration of VM. Multi-Nic, Multi-Disk, in multiple VMs. The deployments will be separated by application ID and function as defined by their owners. This is a very loose grouping that can cause deployments with over 50 virtual machines, with several portgroups associated with the single deployment. I have considered adding vlan as another layer to further break down deployments, but there are still cases where I would want a dynamic number of networks to be available.

I thought the easiest way to gather this information would be to create a nested input array to house all the information per VM. This is the initial version of that idea.

 

formatVersion: 1
inputs:
  vmArray:
    type: array
    title: Virtual Machine Information
    description: Information about the Virtual Machines being provisioned
    minItems: 1
    items:
      type: object
      title: Virtual Machine Object
      description: Individual Virtual Machine
      properties:
        vmName:
          type: string
          title: Virtual Machine Name
          description: Name of the virtual machine being requested using the SECU naming convention
        image:
          type: string
          title: Template
          description: Name of the template being used for this Virtual Machine
          enum:
            - Win2016 Std template
            - Win2019 Std template
          default: Win2016 Std template
        cpu:
          type: object
          title: Virtual Machine CPU Information
          properties:
            totalcores:
              type: integer
              title: Total Cores
              description: Total number of cores. NOT cores per socket. Must be an even number
              min: 2
              max: 256
              default: 2
            sockets:
              type: integer
              title: Sockets
              descrption: Total number of cores must be divisible by number of sockets.
              enum:
                - 1
                - 2
                - 4
              default: 1
        memory:
          type: integer
          title: Memory
          description: Total Memory in GB
          min: 2
          max: 512
          default: 4
        networkArray:
          type: array
          title: Network Information
          minItems: 1
          items:
            type: object
            title: Network configuration per NIC
            properties:
              nicID:
                type: number
                title: NIC ID
                descprtion: ID of NIC between 0 and 3
                min: 0
                max: 3
              assignment:
                type: string
                title: Assignment
                description: Defines whether the IP is Statically or Dynamically defined for NIC.
                enum:
                  - static
                  - dynamic
                default: static
              ipAddress:
                type: string
                title: IP Address
                description: IP address for NIC if statically assigned.
                pattern: '^(?:[0-9]{1,3}\.){3}[0-9]{1,3}$'
              vlanID:
                type: number
                title: VLAN ID
                description: 4 digit VLAN ID associated with network connected to NIC. Example 0024
                pattern: '^[0-9]{4}$'
              gateway:
                type: string
                title: Gateway
                description: Default gateway of the network associated with NIC.
                pattern: '^(?:[0-9]{1,3}\.){3}[0-9]{1,3}$'
              cidr:
                type: string
                title: Subnet CIDR
                description: Subnet Mask in CIDR format. Example 192.168.100.0/24
                pattern: '^(?:[0-9]{1,3}\.){3}[0-9]{1,3}\/[0-9]{1,2}$'
              dnsServers:
                type: array
                title: DNS Servers
                description: DNS Servers for network connected to NIC.
                pattern: '^(?:[0-9]{1,3}\.){3}[0-9]{1,3}$'
              dnsSearchDomain:
                type: array
                title: DNS Search Domains
                description: Search domains use when resolving unqualified names in DNS.
                default: ncsecu.local
              domain:
                type: string
                title: Domain
                description: Domains suffix used for the hostname on this NIC.
        scsiControllers:
          type: integer
          title: SCSI Controllers
          description: Number of SCSI Controllers attached to Virtual Machine
          min: 1
          max: 4
          default: 1
        diskArray:
          type: array
          title: Storage Information
          items:
            type: object
            title: Configuration per additional disk
            properties:
              name:
                type: string
                title: disk name
                description: descriptive name for this disk
                default: Additional Disk
              scsiController:
                type: string
                title: SCSI Controller
                descrption: SCSI Controller for this Disk
                enum:
                  - SCSI_Controller_0
                  - SCSI_Controller_1
                  - SCSI_Controller_2
                  - SCSI_Controller_3
                default: SCSI_Controller_0
              scsiID:
                type: integer
                title: SCSI ID
                description: SCSI ID on SCSI Controller for this DISK (Cannot be 0/0)
                min: 0
                max: 8
                default: 1
              diskSize:
                type: integer
                title: Disk Size GB
                description: Disk size in GB
                min: 1
                max: 4096
                default: 20

 

I planned to use this to hopefully loop through the array and "fill out" the information in the resource portion but I have found that I don't know if the nested arrays will work like I am assuming or at all. I don't know if it is possible to have the count.index unique to the array or if that is just a interchangeable variable.

Here is my resources section... 

 

resources:
  PortGroup:
    type: Cloud.vSphere.Network
    allocatePerInstance: true
    properties:
      networkType: existing
      name: '${"vlan-" + input.vmArray[count.index].networkArray[count.index].vlanID}'
      constraints:
        - tag: '${"vlan:" + input.vmArray[count.index].networkArray[count.index].vlanID}'
      count: '${length(input.vmArray[count.index].networkArray)}'
  VirtualMachine:
    type: Cloud.vSphere.Machine
    recreatePropertiesOnUpdate:
      - vmArray
    allocatePerInstance: true
    properties:
      image: Win2016 Std template
      cpuCount: 4
      count: '${length(input.vmArray)}'
      totalMemoryMB: 1024
      name: '${input.vmarray[*].vmName}'
      networkConfig: '${input.vmArray[count.index].networkArray}'
      networks: '${map_to_object(resource.PortGroup[*].id, "network")}'
      attachedDisks: '${map_to_object(resource.AdditionalDisks[*].id, "source")}'
  AdditionalDisks:
    type: Cloud.vSphere.Disk
    allocatePerInstance: true
    properties:
      capacityGb: '${input.vmArray[count.index].diskArray[count.index].diskSize}'
      count: '${length(input.vmArray[count.index].diskArray)}'
      name: '${input.vmArray[count.index].diskArray[count.index].diskName}'
      SCSIController: '${input.vmArray[count.index].diskArray[count.index].scsiController}'
 

 

 
I have since modified the template to not rely on the nested array but I still have issues with allocating the network object as a cluster as the count fails when its more than 1.
 
By un-nesting the arrays and using the vmName property as a key, I am attempting to filter the objects created to assign what is configured for which vm.
 

 

formatVersion: 1
inputs:
  vmArray:
    type: array
    title: Virtual Machine Information
    description: Information about the Virtual Machines being provisioned
    minItems: 1
    items:
      type: object
      title: Virtual Machine Object
      description: Individual Virtual Machine
      properties:
        vmName:
          type: string
          title: Virtual Machine Name
          description: Name of the virtual machine being requested using the SECU naming convention
        image:
          type: string
          title: Template
          description: Name of the template being used for this Virtual Machine
          enum:
            - Win2016 Std template
            - Win2019 Std template
          default: Win2016 Std template
        cpu:
          type: object
          title: Virtual Machine CPU Information
          properties:
            totalcores:
              type: integer
              title: Total Cores
              description: Total number of cores. NOT cores per socket. Must be an even number
              min: 2
              max: 256
              default: 2
            sockets:
              type: integer
              title: Sockets
              descrption: Total number of cores must be divisible by number of sockets.
              enum:
                - 1
                - 2
                - 4
              default: 1
        memory:
          type: integer
          title: Memory
          description: Total Memory in GB
          min: 2
          max: 512
          default: 4
  networkArray:
    type: array
    title: Network Information
    minItems: 1
    items:
      type: object
      title: Network configuration per NIC
      properties:
        vmName:
          type: string
          title: Virtual Machine Name
          description: Used to associate Network with VM.
        nicID:
          type: number
          title: NIC ID
          descprtion: ID of NIC between 0 and 3
          min: 0
          max: 3
        assignment:
          type: string
          title: Assignment
          description: Defines whether the IP is Statically or Dynamically defined for NIC.
          enum:
            - static
            - dynamic
          default: static
        ipAddress:
          type: string
          title: IP Address
          description: IP address for NIC if statically assigned.
          pattern: '^(?:[0-9]{1,3}\.){3}[0-9]{1,3}$'
        vlanID:
          type: number
          title: VLAN ID
          description: 4 digit VLAN ID associated with network connected to NIC. Example 0024
          pattern: '^[0-9]{4}$'
        gateway:
          type: string
          title: Gateway
          description: Default gateway of the network associated with NIC.
          pattern: '^(?:[0-9]{1,3}\.){3}[0-9]{1,3}$'
        cidr:
          type: string
          title: Subnet CIDR
          description: Subnet Mask in CIDR format. Example 192.168.100.0/24
          pattern: '^(?:[0-9]{1,3}\.){3}[0-9]{1,3}\/[0-9]{1,2}$'
        dnsServers:
          type: array
          title: DNS Servers
          description: DNS Servers for network connected to NIC.
          pattern: '^(?:[0-9]{1,3}\.){3}[0-9]{1,3}$'
        dnsSearchDomain:
          type: array
          title: DNS Search Domains
          description: Search domains use when resolving unqualified names in DNS.
        domain:
          type: string
          title: Domain
          description: Domains suffix used for the hostname on this NIC.
          default: ncsecu.local
  diskArray:
    type: array
    title: Storage Information
    items:
      type: object
      title: Configuration per additional disk
      properties:
        vmName:
          type: string
          title: VM Name
          description: Virtual Machine Name
        name:
          type: string
          title: disk name
          description: descriptive name for this disk
          default: Additional Disk
        scsiController:
          type: string
          title: SCSI Controller
          descrption: SCSI Controller for this Disk
          enum:
            - SCSI_Controller_0
            - SCSI_Controller_1
            - SCSI_Controller_2
            - SCSI_Controller_3
          default: SCSI_Controller_0
        scsiID:
          type: integer
          title: SCSI ID
          description: SCSI ID on SCSI Controller for this DISK (Cannot be 0/0)
          min: 0
          max: 8
          default: 1
        diskSize:
          type: integer
          title: Disk Size GB
          description: Disk size in GB
          min: 1
          max: 4096
          default: 20
resources:
  PortGroup:
    type: Cloud.vSphere.Network
    allocatePerInstance: true
    properties:
      networkType: existing
      name: '${"vlan-" + input.networkArray[count.index].vlanID}'
      constraints:
        - tag: '${"vlan:" + input.networkArray[count.index].vlanID}'
      count: '${length(input.networkArray)}'
      vmname: '${input.networkArray[count.index].vmName}'
  VirtualMachine:
    type: Cloud.vSphere.Machine
    recreatePropertiesOnUpdate:
      - vmConfig
      - diskConfig
      - networkConfig
    allocatePerInstance: true
    properties:
      image: Win2016 Std template
      cpuCount: '${input.vmArray[count.index].cpu.totalcores}'
      count: '${length(input.vmArray)}'
      totalMemoryMB: '${input.vmArray[count.index].memory}'
      name: '${input.vmArray[count.index].vmName}'
      networkConfig: '${input.networkArray}'
      vmConfig: '${input.vmArray}'
      diskConfig: '${input.diskArray}'
      networks: '${map_to_object(filter_by({resource.PortGroup[*]}, vmname => vmname == resource.VirtualMachine.name}).id, "network")}'
      attachedDisks: '${map_to_object(filter_by({resource.AdditionalDisks[*]}, vmname => vmname == resource.VirtualMachine.name}).id, "source")}'
  AdditionalDisks:
    type: Cloud.vSphere.Disk
    allocatePerInstance: true
    properties:
      capacityGb: '${input.diskArray[count.index].diskSize}'
      name: '${input.diskArray[count.index].diskName}'
      SCSIController: '${input.diskArray[count.index].scsiController}'
      count: '${length(input.diskArray)}'
      unitNumber: '${input.diskArray[count.index].scsiID}'
      vmname: '${input.diskArray[count.index].vmName}'

 

 
I am still having issues with the network resource having a count greater than 1 and would like to know if there are ways around that.
 
Thanks for your help!
Labels (2)
0 Kudos
1 Reply
michaelbachmann
Contributor
Contributor

same problem here... tried for hours now but did not found a solution

Tags (1)
0 Kudos