terraform-provider-nutanix icon indicating copy to clipboard operation
terraform-provider-nutanix copied to clipboard

Allow VM cloning

Open yannickstruyf3 opened this issue 4 years ago • 3 comments

Describe the solution you'd like Allow the terraform provider to create a new Virtual Machine by cloning an existing one. VM(s) data source will also be required

Describe alternatives you've considered None

Additional context Clone API documentation: nutanix.dev/reference/prism_central/v3/api/vms/postvmsuuidclone/

yannickstruyf3 avatar Feb 24 '21 16:02 yannickstruyf3

need the same too

tuxtof avatar Mar 03 '21 16:03 tuxtof

@yannickstruyf3 & @tuxtof cloning is already available, it is just undocumented on how to do it, with only a couple of mentions that it even exists. After a number of hours of poking/prodding (Nutanix you really need to improve your documentation), I managed to get cloning to work and to customise the VM.

Long story short, here is an example of a configuration that worked for more:

resource "nutanix_virtual_machine" "vm" {
  name                 = "terraform-test"
  description          = "terraform virtual machine test"
  cluster_uuid         = data.nutanix_clusters.clusters.entities.0.metadata.uuid
  num_vcpus_per_socket = 2
  num_sockets          = 2
  memory_size_mib      = 4096

  # This parent_reference is what actually tells the provider to clone the specified VM
  parent_reference = {
    kind = "vm"
    name = "template-ubuntu1804"
    uuid = "a2563300-3f03-404d-9b40-aac3297b8c26"
  }

  guest_customization_cloud_init_user_data = base64encode(file("cloud-init_user-data.yml"))

  disk_list {

    data_source_reference = {
      kind = "vm"
      name = "template-ubuntu1804"
      uuid = "a2563300-3f03-404d-9b40-aac3297b8c26"
    }

    # Do not touch this, cloning randomly adds a CDROM device and will break if you don't define it here
    device_properties {
      device_type = "CDROM"
      disk_address = {
        device_index = 3
        adapter_type = "IDE"
      }
    }

  }

  serial_port_list {
    index = 0
    is_connected = "true"
  }

  nic_list {
    subnet_uuid = "aca5380d-80af-4f61-8b8b-5c2bb2da8add"
  }
}

rolffujino avatar Aug 31 '21 04:08 rolffujino

@yannickstruyf3, @lxkm, & @tuxtof after further development I have found some gotchas:

  • Not all information is stored in the state file, namely 'parent_reference', so every terraform run will reboot the VM, but not destroy it or clone over the top of it.
  • Cloning like in the GUI doesn't allow full VM customisation, e.g. adding serial ports, etc and as such require multiple runs to achieve the desired target state.
  • Leading on from the above line, certain resources like 'serial_port_list' are not recorded in state or are not added on clone, but are considered important enough to trigger terraform to destroy and recreate the VM, which is another clone, so all subsequent runs will cause a repeating cycle of creation and destruction.

Below is the best configuration I have found to date that allows for cloning and guest OS customisation:

resource "nutanix_virtual_machine" "vm" {
  count                = 1
  name                 = "${var.name}${format("%03d", count.index + 1)}"
  description          = "Test VM"
  cluster_uuid         = data.nutanix_clusters.clusters.entities.0.metadata.uuid
  num_vcpus_per_socket = 1
  num_sockets          = 4
  memory_size_mib      = 8192

  # This parent_reference is what actually tells the provider to clone the specified VM
  parent_reference = {
    kind = "vm"
    name = "template-ubuntu1804"
    uuid = "a2563300-3f03-404d-9b40-aac3297b8c26"
  }

  guest_customization_cloud_init_user_data = base64encode(templatefile("${path.module}/cloud-init_user-data.tpl", {
    domain         = var.domain
    hostname       = "${var.name}${format("%03d", count.index + 1)}"
    ipv4_address   = "10.1.1.10/24"
    ipv4_gateway   = "10.1.1.254"
    name_server    = "[10.1.1.1, 10.1.1.2]"
  }))

  disk_list {
    device_properties {
      device_type = "DISK"
      disk_address = {
        adapter_type = "SCSI"
        device_index = 0
      }
    }
  }

  # Do not touch anything in this disk list resource, cloning randomly adds a CDROM device and will break if you don't define it here, as it will try and flatten this device...
  disk_list {
    disk_size_bytes        = 382976
    disk_size_mib          = 1

    device_properties {
      device_type = "CDROM"
      disk_address = {
        adapter_type = "IDE"
        device_index = 3
      }
    }
  }

  nic_list {
    subnet_uuid = "aca5380d-80af-4f61-8b8b-5c2bb2da8add"
  }
}

Referenced above cloud-init_user-data.tpl file:

#cloud-config
write_files:
  - content: |
      network:
        version: 2
        ethernets:
          ens3:
            addresses:
            - ${ipv4_address}
            gateway4: ${ipv4_gateway}
            nameservers:
              addresses: ${name_server}
              search: [${domain}]
    path: /etc/netplan/50-cloud-init.yaml
hostname: ${hostname}
fqdn: ${hostname}.${domain}
manage_etc_hosts: true
runcmd: 
  - netplan apply

rolffujino avatar Aug 31 '21 23:08 rolffujino