Create VM on terraform with vmware

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

Hi @babagadji ,

Can you please give us more detail for example the terraform yaml file

Regard

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.