hashicorp / terraform-provider-vsphere

Terraform Provider for VMware vSphere
https://registry.terraform.io/providers/hashicorp/vsphere/
Mozilla Public License 2.0
623 stars 453 forks source link

ovf_mapping ForceNew prevents adding new interfaces to VMs created from content library #1313

Open axelrtgs opened 3 years ago

axelrtgs commented 3 years ago

Community Guidelines

Description

https://github.com/hashicorp/terraform-provider-vsphere/blob/3b1d5a379663f08f37a65b7d3c1406baad3c4259/vsphere/internal/virtualdevice/virtual_machine_network_interface_subresource.go#L107-L112

When adding a new network interface to a VM created from a content library OVF template it tries to replace the VM. This behaviour is not desired for us.

Once the VM is up and running, adding an interface should not recreate the entire VM. When creating a VM from an OVF template you need to specify an OVF Mapping field. This field is ignored once the VM is created. There is no validation on the vmware side that the mappings actually exist in the OVF only that they are unique. It is possible to use random strings in the ovf_mapping property VMware will still create the VM for you.

Is there a possibility of changing this to not force the vm recreation when adding interfaces to VMs created from OVF? This is useful when using the content library to store templates for distribution. We expect them to behave like regular templates where we can add interfaces without recreating the VM.

Thanks

EDIT::

A proposed solution might be to keep the ForceNew but when deploying from content library OVF template and ovf_mapping is not set initialize it to some unique value when generating the API call to satisfy the vsphere api. This would be both compatible with the current behaviour to force recreation when the value changes but also be compatible with templates that don't have rigid mappings and assign additional interfaces at creation time.

joerr1 commented 3 years ago

We're currently experiencing this problem. Has a fix been found for this? @axelrtgs

tenthirtyam commented 2 years ago

Community Note:

Vote on this issue by adding a πŸ‘ reaction to the original issue initial description to help the maintainers prioritize.


I took some time to test this scenario today using the following:

provider "vsphere" {
  vsphere_server       = var.vsphere_server
  user                 = var.vsphere_username
  password             = var.vsphere_password
  allow_unverified_ssl = var.vsphere_insecure
}

data "vsphere_datacenter" "datacenter" {
  name = var.vsphere_datacenter
}

data "vsphere_network" "network" {
  name          = var.vsphere_network
  datacenter_id = data.vsphere_datacenter.datacenter.id
}

data "vsphere_compute_cluster" "cluster" {
  name          = var.vsphere_cluster
  datacenter_id = data.vsphere_datacenter.datacenter.id
}

data "vsphere_resource_pool" "pool" {
  name          = format("%s%s", data.vsphere_compute_cluster.cluster.name, "/Resources")
  datacenter_id = data.vsphere_datacenter.datacenter.id
}

data "vsphere_datastore" "datastore" {
  name          = var.vsphere_datastore
  datacenter_id = data.vsphere_datacenter.datacenter.id
}

data "vsphere_content_library" "content_library" {
  name = var.vsphere_content_library
}

data "vsphere_content_library_item" "content_library_item" {
  name       = var.vsphere_content_library_ovf
  type       = "ovf"
  library_id = data.vsphere_content_library.content_library.id
}

resource "vsphere_virtual_machine" "vm" {
  name                    = var.vm_name
  folder                  = var.vsphere_folder
  num_cpus                = var.vm_cpus
  memory                  = var.vm_memory
  firmware                = var.vm_firmware
  efi_secure_boot_enabled = var.vm_efi_secure_boot_enabled
  datastore_id            = data.vsphere_datastore.datastore.id
  resource_pool_id        = data.vsphere_resource_pool.pool.id
  network_interface {
    network_id = data.vsphere_network.network.id
  }
  disk {
    label            = "disk0"
    size             = var.vm_disk_size
    thin_provisioned = true
  }
  clone {
    template_uuid = data.vsphere_content_library_item.content_library_item.id
    customize {
      linux_options {
        host_name = var.vm_hostname
        domain    = var.vm_domain
      }
      network_interface {
        ipv4_address = var.vm_ipv4_address_0
        ipv4_netmask = var.vm_ipv4_netmask
      }

      ipv4_gateway    = var.vm_ipv4_gateway
      dns_suffix_list = var.vm_dns_suffix_list
      dns_server_list = var.vm_dns_server_list
    }
  }
  lifecycle {
    ignore_changes = [
      clone[0].template_uuid,
    ]
  }
}

After deployment of the OVF Template from the content library, add additional network interfaces...

resource "vsphere_virtual_machine" "vm" {
  name                    = var.vm_name
  folder                  = var.vsphere_folder
  num_cpus                = var.vm_cpus
  memory                  = var.vm_memory
  firmware                = var.vm_firmware
  efi_secure_boot_enabled = var.vm_efi_secure_boot_enabled
  datastore_id            = data.vsphere_datastore.datastore.id
  resource_pool_id        = data.vsphere_resource_pool.pool.id
  network_interface {
    network_id = data.vsphere_network.network.id
  }
  network_interface {
    network_id = data.vsphere_network.network.id
  }
  disk {
    label            = "disk0"
    size             = var.vm_disk_size
    thin_provisioned = true
  }
  clone {
    template_uuid = data.vsphere_content_library_item.content_library_item.id
    customize {
      linux_options {
        host_name = var.vm_hostname
        domain    = var.vm_domain
      }
      network_interface {
        ipv4_address = var.vm_ipv4_address_0
        ipv4_netmask = var.vm_ipv4_netmask
      }
      network_interface {
        ipv4_address = var.vm_ipv4_address_1
        ipv4_netmask = var.vm_ipv4_netmask
      }

      ipv4_gateway    = var.vm_ipv4_gateway
      dns_suffix_list = var.vm_dns_suffix_list
      dns_server_list = var.vm_dns_server_list
    }
  }
  lifecycle {
    ignore_changes = [
      clone[0].template_uuid,
    ]
  }
}

Running terraform apply results in destruction.

Plan: 1 to add, 0 to change, 1 to destroy.
vsphere_virtual_machine.vm: Destroying... [id=4202838d-ba9c-bb0a-01bf-c595e95fa00c]
vsphere_virtual_machine.vm: Destruction complete after 8s

However, simply removing the ForceNew from the ovf_deploy for the sub-resources does not address the issue and the results are the same. _(I performed some tests with this, too.).

This aside, this is not an ideal scenario as the content library is used to redistribute baseline machine images that may or may not need additional interfaces based on the use case.

Marking as confirmed.

Ryan Johnson Staff II Solutions Architect | VMware, Inc.

jakegroves commented 2 years ago

Any further information on this being picked up?

joedwards32 commented 2 years ago

Also having this issue.

Ilhaame commented 2 years ago

Hello, Any news ? Because we have the same problems...

tenthirtyam commented 2 years ago

Community Note

burnsjared0415 commented 3 months ago

i looked at this and it does not even create a new interface on recreate, i believe there might be other issues here.