Search code examples
terraformvsphere

Terraform Module for VMware VMs


I am creating a module for VM creation in VMware, and I'm looking to clone a VM template. The hangup is when adding more disks than just the single disk that the template provides or adding a disk in the future if needed.

I don't know if adding another disk section in the virtual machine resource and setting the variable type to map using interpolation syntax would work.

It would be nice if there was a way to use something like jinja for templating.

Module work in progress:

data "vsphere_datacenter" "dc" {
  name = "${var.vmw_dc}"
}

data "vsphere_datastore" "datastore" {
  name          = "${var.vmw_datastore}"
  datacenter_id = "${data.vsphere_datacenter.dc.id}"
}

data "vsphere_resource_pool" "pool" {
  name          = "${var.vmw_cluster}"
  datacenter_id = "${data.vsphere_datacenter.dc.id}"
}

data "vsphere_network" "network" {
  name          = "${var.vmw_network}"
  datacenter_id = "${data.vsphere_datacenter.dc.id}"
}

resource "vsphere_virtual_machine" "vm" {
  name             = "${var.vm_name}"
  resource_pool_id = "${data.vsphere_resource_pool.pool.id}"
  datastore_id     = "${data.vsphere_datastore.datastore.id}"

  num_cpus = "${var.vm_cpu}"
  memory   = "${var.vm_mem}"
  guest_id = "${var.vm_GuestType}"

  network_interface {
    network_id = "${data.vsphere_network.network.id}"
  }

  disk {
    label = "disk0"
    size  = 20
  }
  disk {
    label = "${var.vm_disk.*.label, count.index}"
  }
}

Doing this as a non-module would be easy. Just have a bunch of resource declarations like the above code, or creating a module and just passing the variables through in module per VM needing created.

The above would work for a single disk VM if you ignore the second Disk declaration. But if I need to add the second disk then a second disk declaration is needed and a third and so on.

So I want to be sure, if creating a map or a list of map variable that contains Disk2 through X, then in the second disk declaration the other disks will get rendered when executing terraform plan.

"vm_disk" = {
  Disk2 = {label=X,Size=X,Position=X},
  Disk3 = {label=X,Size=X,Position=X},
  Disk4 = {label=X,Size=X,Position=X},
}

Solution

  • There's not currently a way to have dynamic amounts of sub resources in Terraform so you can't simply use something like:

    resource "vsphere_virtual_machine" "vm" {
      ...
      disk {
        count = "${length(var.disks)}"
        ...
      }
    }
    

    In other providers such as AWS your module could create an instance without any ebs_block_device sub resources of the aws_instance resource but then use separate aws_ebs_volume resources to create separate disks and then attach with the aws_volume_attachment resource which, because they are all top level resources, allow you to use the count meta parameter to dynamically set the amount of volumes each instance gets.

    While the VSphere provider does offer a separate vsphere_virtual_disk resource the only way to attach these separate disk resources to a VM is by using the attach parameter of the disk sub resource so you would be unable to dynamically attach different amounts of disks in your module.