Terraform: vsphere_virtual_maschine vmdk import

I’m sure that’s a silly question. But I have the following problem that I do not understand how to solve this with terraform.

In my setup a vmdk is created with packer and automatically loaded into a specific directory on a vcenter. This is our CI/CD. Now I want to easily create different virtual machines from this VMDK. But somehow I do not get this done. I can only attache the vmdk. However, I want to clone this vmdk and create a virtual machine from it. So that the uploaded VMDK is not changed. No matter how I do it, it does not work as expected.

With this terraform file it goes somewhat but, I have then the folders debian and debian_1
In the folder debian is the vmdk and in the folder debian_1 is the description of the virtual machine. But a terraform destroy does not clean up everything. When I do a terraform apply again it tells me that the vmdk is already there in the directory debian.

Could you tell me howto make a clone from a already upload vmdk with terraform?

## Configure the vSphere Provider
provider "vsphere" {
        vsphere_server = var.vsphere-vcenter
        user = var.vsphere-user
        password = var.vsphere-password
        allow_unverified_ssl = true
}

## Build VM
data "vsphere_datacenter" "dc" {
        name = "Datacenter"
}

data "vsphere_datastore" "datastore" {
        name = "datastore1"
        datacenter_id = data.vsphere_datacenter.dc.id
}

data "vsphere_datastore" "vmdatastore" {
        name = "VM_Datastore"
        datacenter_id = data.vsphere_datacenter.dc.id
}

data "vsphere_resource_pool" "pool" {
        name = "terraform"
        datacenter_id = data.vsphere_datacenter.dc.id
}

data "vsphere_network" "wan" {
        name = "IN_NAT"
        datacenter_id = data.vsphere_datacenter.dc.id
}

data "vsphere_network" "lan" {
        name = "Testnetz_Service_3"
        datacenter_id = data.vsphere_datacenter.dc.id
}

resource "vsphere_file" "copy_apos" {
        source_datacenter = "Datacenter"
        datacenter = "Datacenter"
        source_datastore = "datastore1"
        datastore = "VM_Datastore"
        source_file = "/debian/master/9.1/debian.vmdk"
        destination_file  = "/debian/debian.vmdk"
        create_directories = true
}

resource "vsphere_virtual_machine" "server" {
        name = "debian"
        resource_pool_id = data.vsphere_resource_pool.pool.id
        datastore_id = data.vsphere_datastore.vmdatastore.id

        num_cpus = 2
        memory = 1024
        guest_id = "other3xLinux64Guest"
        annotation = "Deployed by tarraform"
        wait_for_guest_net_timeout = 0

        network_interface {
                network_id = data.vsphere_network.wan.id
        }

        network_interface {
                network_id = data.vsphere_network.lan.id
        }

        disk {
                label = "disk0"
                attach = true
                path = "/debian/debian.vmdk"
                datastore_id = data.vsphere_datastore.vmdatastore.id
        }
}

Hi @feckert ,
would your design allow to create a VM-template using packer and run the deployment based on that?
Which terraform version and provider version are you using?

The clone block would be comparable to:

  clone {
    template_uuid = data.vsphere_virtual_machine.template.id
    customize {
      linux_options {
        host_name = var.vsphere_virtual_machine_name
        domain    = var.vsphere_virtual_machine_domain
      }
      network_interface {
      }
    }
  }

@tbugfinder Thanks for your quick reply :+1:
The CI/CD process to upload the VMDK’s I have not under my control.
This process is done with packer on virtualbox. We do not have enough license for vmmware to handle the build process on a vmware system. So we build the vmdk for our appliance in virtualbox and then only use that. The hardware description should then happen in vcenter.
Until now we have always manually created the machines from the VMDK’s in the vcenter over the UI.

I wanted to improve this now with terraform, because the manual creation of the vm´s with the uploaded vmdk´s is error prone and annoying.

Version:
Terraform is v0.14.5
vsphere provider is 1.24.3

Is there no way in terraform to generate a vm or template from an existing vmdk on the vcenter?

I have now managed to upload the vmdk from my workstation and not use the one from vcenter directly. So far so good.

Only now I have 2 new problems.

  1. when uploading it then terraform tells me the following.
vsphere_file.copy_apos: Creating...
vsphere_virtual_machine.server: Creating...
vsphere_file.copy_apos: Creation complete after 7s [id=[VM_Datastore] Datacenter/debian-VMDK/debian.vmdk]

Error: error creating virtual machine: File []/vmfs/volumes/5eb8fcea-8ba7426e-9346-001e6799bae1/debian-VMDK/debian.vmdk was not found

  on main.tf line 47, in resource "vsphere_virtual_machine" "server":
  47: resource "vsphere_virtual_machine" "server" {


FAIL: 1

So I have to run the apply again to create the VM.

  1. If I want to destroy my setup with terraform destroy, then the file debian-VMDK-flat.vmdk remains in the debian-vmdk directory, which requires manual intervention, otherwise I can’t run the terraform apply again.
## Configure the vSphere Provider
provider "vsphere" {
        vsphere_server = var.vsphere-vcenter
        user = var.vsphere-user
        password = var.vsphere-password
        allow_unverified_ssl = true
}

## Build VM
data "vsphere_datacenter" "dc" {
        name = "Datacenter"
}

data "vsphere_datastore" "datastore" {
        name = "datastore1"
        datacenter_id = data.vsphere_datacenter.dc.id
}

data "vsphere_datastore" "vmdatastore" {
        name = "VM_Datastore"
        datacenter_id = data.vsphere_datacenter.dc.id
}

data "vsphere_resource_pool" "pool" {
        name = "terraform"
        datacenter_id = data.vsphere_datacenter.dc.id
}

data "vsphere_network" "wan" {
        name = "IN_NAT"
        datacenter_id = data.vsphere_datacenter.dc.id
}

data "vsphere_network" "lan" {
        name = "Testnetz_Service_3"
        datacenter_id = data.vsphere_datacenter.dc.id
}

resource "vsphere_file" "copy_debian" {
        datacenter = "Datacenter"
        datastore = "VM_Datastore"
        source_file = "debian.vmdk"
        destination_file  = "debian-VMDK/debian.vmdk"
        create_directories = true
}

resource "vsphere_virtual_machine" "server" {
        name = "debian"
        resource_pool_id = data.vsphere_resource_pool.pool.id
        datastore_id = data.vsphere_datastore.vmdatastore.id

        num_cpus = 2
        memory = 1024
        guest_id = "other3xLinux64Guest"
        annotation = "Deployed by tarraform"
        wait_for_guest_net_timeout = 0

        network_interface {
                network_id = data.vsphere_network.wan.id
        }

        network_interface {
                network_id = data.vsphere_network.lan.id
        }

        disk {
                label = "disk0"
                attach = true
                path = "debian-VMDK/debian.vmdk"
                datastore_id = data.vsphere_datastore.vmdatastore.id
        }
}