I am using terraform for virtual machine provisioning with vsphere. The problem I currently encounter is when I create a first vm without working but when I try to create another with different parameters (vm name, IP address, CPU, Memory, …), terraform destroys the vm that I created recently and replaced it with the new one. I don’t understand how it works.
Try to give different resource name, I am guessing you have given same name to the second resource also
Hello @shbhmtwr19,
Thank you for your reply.
Yes indeed I use a terraform module which allows me to create either a linux or windows VM. So I created a resource for linux and another for windows.
Hello @mmkmou,
Thanks you for your reply.
Of course, I currently use terraform version v1.4.0 in which I created a module called terraform-vsphere-vm which allows me to create a linux or windows VM via the vsphere_virtual_machine resource of terraform.
=====
[tacacs15@mesvappterrafprd1 modules]$ ls -lrt …/modules/terraform-vsphere-vm
total 28
-rw-rw-r-- 1 tacacs15 tacacs15     0 22 mai   13:36 output.tf
-rw-rw-r-- 1 tacacs15 tacacs15 10448 24 mai   14:58 main.tf
-rw-rw-r-- 1 tacacs15 tacacs15 13478 24 mai   15:01 variables.tf
Here is my configuration file which I use to deploy my virtual machines?
data “vsphere_datacenter” “dc” {
name = var.dc
}
data “vsphere_datastore” “datastore” {
count         = var.datastore != “” ? 1 : 0
name          = var.datastore
datacenter_id = data.vsphere_datacenter.dc.id
}
data “vsphere_compute_cluster” “cluster” {
count         = var.cluster != “” ? 1 : 0
name          = var.cluster
datacenter_id = data.vsphere_datacenter.dc.id
}
data “vsphere_network” “network” {
name = var.network
datacenter_id = data.vsphere_datacenter.dc.id
}
data “vsphere_virtual_machine” “template” {
count         = var.content_library == null ? 1 : 0
name          = var.vmtemp
datacenter_id = data.vsphere_datacenter.dc.id
}
data “vsphere_content_library” “library” {
count      = var.content_library != null ? 1 : 0
name       = var.content_library
depends_on = [var.tag_depends_on]
}
data “vsphere_tag” “tag” {
count       = var.tags != null ? length(var.tags) : 0
name        = var.tags[keys(var.tags)[count.index]]
category_id = data.vsphere_tag_category.category[count.index].id
depends_on  = [var.tag_depends_on]
}
data “vsphere_tag_category” “category” {
count      = var.tags != null ? length(var.tags) : 0
name       = keys(var.tags)[count.index]
depends_on = [var.tag_depends_on]
}
data “vsphere_content_library_item” “library_item_template” {
count      = var.content_library != null ? 1 : 0
library_id = data.vsphere_content_library.library[0].id
type       = “ovf”
name       = var.vmtemp
depends_on = [var.tag_depends_on]
}
output cl {
value = data.vsphere_virtual_machine.template
}
//Cloning a Linux VM from a given template.
resource “vsphere_virtual_machine” “vm-linux” {
count      = “${var.template_os_family == “linux” ? var.instances : 0}”
depends_on = [var.vm_depends_on]
name       = var.staticvmname != null ? var.staticvmname : format(“${var.vmname}${var.Env}${var.vmnameformat}”, count.index + 1)
resource_pool_id        = data.vsphere_compute_cluster.cluster[0].resource_pool_id
folder                  = var.vmfolder
tags                    = var.tag_ids != null ? var.tag_ids : data.vsphere_tag.tag[*].id
custom_attributes       = var.custom_attributes
annotation              = “Serveur: ${format(”${var.vmname}${var.Env}${var.vmnameformat}“, count.index + 1)}”
extra_config            = var.extra_config
firmware                = var.content_library == null && var.firmware == null ? data.vsphere_virtual_machine.template[0].firmware : var.firmware
efi_secure_boot_enabled = var.content_library == null && var.efi_secure_boot == null ? data.vsphere_virtual_machine.template[0].efi_secure_boot_enabled : var.efi_secure_boot
enable_disk_uuid        = var.content_library == null && var.enable_disk_uuid == null ? data.vsphere_virtual_machine.template[0].enable_disk_uuid : var.enable_disk_uuid
storage_policy_id       = var.storage_policy_id
datastore_id = var.datastore != “” ? data.vsphere_datastore.datastore[0].id : null
num_cpus               = var.cpu_number
num_cores_per_socket   = var.num_cores_per_socket
cpu_hot_add_enabled    = var.cpu_hot_add_enabled
cpu_hot_remove_enabled = var.cpu_hot_remove_enabled
cpu_reservation        = var.cpu_reservation
cpu_share_level        = var.cpu_share_level
cpu_share_count        = var.cpu_share_level == “custom” ? var.cpu_share_count : null
memory_reservation     = var.memory_reservation
memory                 = var.ram_size
memory_hot_add_enabled = var.memory_hot_add_enabled
memory_share_level     = var.memory_share_level
memory_share_count     = var.memory_share_level == “custom” ? var.memory_share_count : null
guest_id               = var.content_library == null ? data.vsphere_virtual_machine.template[0].guest_id : null
scsi_bus_sharing       = var.scsi_bus_sharing
scsi_type              = var.scsi_type != “” ? var.scsi_type : (var.content_library == null ? data.vsphere_virtual_machine.template[0].scsi_type : null)
wait_for_guest_net_routable = var.wait_for_guest_net_routable
wait_for_guest_ip_timeout   = var.wait_for_guest_ip_timeout
wait_for_guest_net_timeout  = var.wait_for_guest_net_timeout
network_interface {
network_id = data.vsphere_network.network.id
}
disk {
label = data.vsphere_virtual_machine.template[0].disks[0].label
size = data.vsphere_virtual_machine.template[0].disks[0].size
thin_provisioned = data.vsphere_virtual_machine.template[0].disks[0].thin_provisioned
}
//clone
clone {
template_uuid = var.content_library == null ? data.vsphere_virtual_machine.template[0].id : data.vsphere_content_library_item.library_item_template[0].id
linked_clone  = var.linked_clone
timeout       = var.timeout
customize {
  dynamic "linux_options" {
    for_each = var.template_os_family == "linux" ? [1] : []
    content {
      host_name    = var.staticvmname != null ? var.staticvmname : format("${var.vmname}${var.Env}${var.vmnameformat}", count.index + 1)
      domain       = var.domain
      hw_clock_utc = var.hw_clock_utc
    }
  }
  dynamic "network_interface" {
    for_each = toset(var.ipaddress)
    content {
      ipv4_address = var.ipaddress[count.index]
      ipv4_netmask = var.mask
    }
  }
  dns_server_list = var.dns_server_list
  dns_suffix_list = var.dns_suffix_list
  ipv4_gateway    = var.vmgateway
}
}
}
############################################################################################################
//Cloning a Windows VM from a given template.
resource “vsphere_virtual_machine” “vm-windows” {
count      = “${var.template_os_family == “windows” ? var.instances : 0}”
depends_on = [var.vm_depends_on]
name       = var.staticvmname != null ? var.staticvmname : format(“${var.vmname}${var.Env}${var.vmnameformat}”, count.index + 1)
resource_pool_id        = data.vsphere_compute_cluster.cluster[0].resource_pool_id
folder                  = var.vmfolder
tags                    = var.tag_ids != null ? var.tag_ids : data.vsphere_tag.tag[*].id
custom_attributes       = var.custom_attributes
annotation              = “Serveur: ${format(”${var.vmname}${var.Env}${var.vmnameformat}“, count.index + 1)}”
extra_config            = var.extra_config
firmware                = var.content_library == null && var.firmware == null ? data.vsphere_virtual_machine.template[0].firmware : var.firmware
efi_secure_boot_enabled = var.content_library == null && var.efi_secure_boot == null ? data.vsphere_virtual_machine.template[0].efi_secure_boot_enabled : var.efi_secure_boot
enable_disk_uuid        = var.content_library == null && var.enable_disk_uuid == null ? data.vsphere_virtual_machine.template[0].enable_disk_uuid : var.enable_disk_uuid
storage_policy_id       = var.storage_policy_id
datastore_id = var.datastore != “” ? data.vsphere_datastore.datastore[0].id : null
num_cpus               = var.cpu_number
num_cores_per_socket   = var.num_cores_per_socket
cpu_hot_add_enabled    = var.cpu_hot_add_enabled
cpu_hot_remove_enabled = var.cpu_hot_remove_enabled
cpu_reservation        = var.cpu_reservation
cpu_share_level        = var.cpu_share_level
cpu_share_count        = var.cpu_share_level == “custom” ? var.cpu_share_count : null
memory_reservation     = var.memory_reservation
memory                 = var.ram_size
memory_hot_add_enabled = var.memory_hot_add_enabled
memory_share_level     = var.memory_share_level
memory_share_count     = var.memory_share_level == “custom” ? var.memory_share_count : null
guest_id               = var.content_library == null ? data.vsphere_virtual_machine.template[0].guest_id : null
scsi_bus_sharing       = var.scsi_bus_sharing
scsi_type              = var.scsi_type != “” ? var.scsi_type : (var.content_library == null ? data.vsphere_virtual_machine.template[0].scsi_type : null)
wait_for_guest_net_routable = var.wait_for_guest_net_routable
wait_for_guest_ip_timeout   = var.wait_for_guest_ip_timeout
wait_for_guest_net_timeout  = var.wait_for_guest_net_timeout
network_interface {
network_id = data.vsphere_network.network.id
}
disk {
label = data.vsphere_virtual_machine.template[0].disks[0].label
size = data.vsphere_virtual_machine.template[0].disks[0].size
thin_provisioned = data.vsphere_virtual_machine.template[0].disks[0].thin_provisioned
}
//clone
clone {
template_uuid = var.content_library == null ? data.vsphere_virtual_machine.template[0].id : data.vsphere_content_library_item.library_item_template[0].id
linked_clone  = var.linked_clone
timeout       = var.timeout
customize {
  dynamic "windows_options" {
    for_each = var.template_os_family == "windows" ? [1] : []
    content {
      computer_name         = var.staticvmname != null ? var.staticvmname : format("${var.vmname}${var.Env}${var.vmnameformat}", count.index + 1)
      admin_password        = var.local_adminpass
      workgroup             = var.workgroup
      join_domain           = var.windomain
      domain_admin_user     = var.domain_admin_user
      domain_admin_password = var.domain_admin_password
      organization_name     = var.orgname
      run_once_command_list = var.run_once
      auto_logon            = var.auto_logon
      auto_logon_count      = var.auto_logon_count
      time_zone             = var.time_zone
      product_key           = var.productkey
      full_name             = var.full_name
    }
  }
dynamic "network_interface" {
  for_each = toset(var.ipaddress)
  content {
    ipv4_address = var.ipaddress[count.index]
    ipv4_netmask = var.mask
  }
}
dns_server_list = var.dns_server_list
dns_suffix_list = var.dns_suffix_list
ipv4_gateway    = var.vmgateway
}
}
// Advanced options
hv_mode                          = var.hv_mode
ept_rvi_mode                     = var.ept_rvi_mode
nested_hv_enabled                = var.nested_hv_enabled
enable_logging                   = var.enable_logging
cpu_performance_counters_enabled = var.cpu_performance_counters_enabled
swap_placement_policy            = var.swap_placement_policy
latency_sensitivity              = var.latency_sensitivity
shutdown_wait_timeout = var.shutdown_wait_timeout
force_power_off       = var.force_power_off
===========
NB:
I explain the context, we very often have requests for VM provisioning and it differs depending on the project. We can have a request for a project A in which we must create 4 VMs for example. When I use my configuration file to deploy these 4 VMs with terraform it works. Terraform creates them fine in VMWARE. However, if I have another request from another project that initially requires only 2 VMs, when launching my terraform, it replaces these two VMs with the 2 VMs of the 4 VMs that I had created for project A and remove the other two. For information I thought of the Workspace but I will have the same concern because I may have for project A, a request to create 4 vms and some time later I may have another request to add 2 new VMs for this same project, which comes to me at 6 Vms for this same project.