Search code examples
terraformpackervsphereterraform-provider-vspherehashicorp-packer

Terraform vSphere new template re-creating existing VMs


I use Packer to create Linux template image. Using Terraform I deploy the VMs using the template image. But whenever I update the template and trying to create the new VM. Terraform Destroying existing VMs and re-creating it.

When I re-create the new template image, I don’t want to impact the existing VMs, I want only new VM to be created using new template. How to handle this kind situation?

Here is the Terraform code I use to create the VMs.

# =================== #
# Deploying VMware VM #
# =================== #

# Connect to VMware vSphere vCenter
provider "vsphere" {
  user = var.vsphere-user
  password = var.vsphere-password
  vsphere_server = var.vsphere-vcenter

  # If you have a self-signed cert
  allow_unverified_ssl = var.vsphere-unverified-ssl
}

# Define VMware vSphere 
data "vsphere_datacenter" "dc" {
  name = var.vsphere-datacenter
}

data "vsphere_datastore" "datastore" {
  name = var.vm-datastore
  datacenter_id = data.vsphere_datacenter.dc.id
}

data "vsphere_compute_cluster" "cluster" {
  name = var.vsphere-cluster
  datacenter_id = data.vsphere_datacenter.dc.id
}

data "vsphere_network" "network" {
  name = var.vm-network
  datacenter_id = data.vsphere_datacenter.dc.id
}

data "vsphere_virtual_machine" "template" {
  name = var.vm-template-name
  datacenter_id = data.vsphere_datacenter.dc.id
}

# Create VMs
resource "vsphere_virtual_machine" "vm" {
  count = var.vm-count
  # VM Name
  name = upper(var.vm-name)
  resource_pool_id = data.vsphere_compute_cluster.cluster.resource_pool_id
  datastore_id = data.vsphere_datastore.datastore.id
 
  # System
  guest_id = data.vsphere_virtual_machine.template.guest_id
  scsi_type = data.vsphere_virtual_machine.template.scsi_type
  firmware = data.vsphere_virtual_machine.template.firmware

  # CPU
  num_cpus = var.vm-cpu
  num_cores_per_socket = 2
  cpu_hot_add_enabled = true
  cpu_hot_remove_enabled = true

  # Memory
  memory = var.vm-ram
  memory_hot_add_enabled = true

  network_interface {
    network_id = data.vsphere_network.network.id
    adapter_type = data.vsphere_virtual_machine.template.network_interface_types[0]
  }

  disk {
    label = "disk0"
    size = data.vsphere_virtual_machine.template.disks.0.size
    eagerly_scrub = data.vsphere_virtual_machine.template.disks.0.eagerly_scrub
    thin_provisioned = data.vsphere_virtual_machine.template.disks.0.thin_provisioned
    unit_number = 0
  }
  disk {
    label = "disk1"
    unit_number = 1
    size = 1
    eagerly_scrub = data.vsphere_virtual_machine.template.disks.0.eagerly_scrub
    thin_provisioned = data.vsphere_virtual_machine.template.disks.0.thin_provisioned

  }
  clone {
    template_uuid = data.vsphere_virtual_machine.template.id
    customize {
      timeout = 15

      linux_options {
        host_name = lower(var.vm-name)
        domain = var.vm-domain
      }

      network_interface {
        ipv4_address = var.vm-ip
        ipv4_netmask = var.vm-netmask
      }
      ipv4_gateway = var.vm-gateway
      dns_suffix_list = var.vm-dns-suffix-list
      dns_server_list = var.vm_dns_servers
    }
  }
}

Solution

  • This is an older question, but there is another way of handling this with the lifecycle meta-argument. If you add something like the following, it should tell Terraform to ignore changes to the template's UUID:

      clone {
        template_uuid = data.vsphere_virtual_machine.template.id
      }
    
      lifecycle {
        ignore_changes = [
          clone[0].template_uuid,
        ]
      }
    

    This should let you avoid UUID updates when the template changes.

    Code taken from the relevant Github Issue.