terraform-provider-nutanix
terraform-provider-nutanix copied to clipboard
Allow VM cloning
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/
need the same too
@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"
}
}
@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