taliesins / terraform-provider-hyperv

HyperV provider for Terraform
Mozilla Public License 2.0
231 stars 80 forks source link

"hard_disk_drives" path not being able to read the correct variable value #205

Open Wei-Yo opened 1 year ago

Wei-Yo commented 1 year ago

Hi there,

Thank you for developing this project, which helps me integrate Terraform with Hyper-V.

In my environment, I am cloning a VM template based on your example, here: https://github.com/taliesins/terraform-provider-hyperv/blob/master/examples/clone-existing-vm/main.tf

But in my environment, I encountered the following error when running the command: image

It seems like the error is caused by the "hard_disk_drives" path not being able to read the correct variable value of "D:\VM\test\test.vhdx".

Terraform Version

image

Affected Resource(s)

resource "hyperv_vhd" resource "hyperv_machine_instance"

Terraform Configuration Files

main.tf
#===============================================================================
# Terraform
#===============================================================================
terraform {
  required_providers {
    hyperv = {
      version = "1.0.3"
      source  = "registry.terraform.io/taliesins/hyperv"
    }
  }
}

#===============================================================================
# HyperV Provider
#===============================================================================
provider "hyperv" {
  host            = "${var.hyperv_server}"
  port            = "${var.hyperv_serverPort}"
  user            = "${var.hyperv_user}"
  password        = "${var.hyperv_password}"
  insecure        = "${var.hyperv_sslSkip}"
}

#===============================================================================
# HyperV Data
#===============================================================================
data "hyperv_network_switch" "defaultNetwork" {
  name = "${var.vm_network}"
}

data "hyperv_machine_instance" "template" {
  name = "${var.vm_templateName}"
}

#===============================================================================
#  HyperV Resources
#===============================================================================
resource "hyperv_vhd" "vm_vhd" {
  path = "${var.vm_path}\\${var.vm_hostname}\\${var.vm_hostname}.vhdx"
  source_vm = data.hyperv_machine_instance.template.name
}

resource "hyperv_machine_instance" "vm_instance" {
  name                   = "${var.vm_hostname}"
  processor_count        = "${var.vm_cpu}"
  memory_startup_bytes   = "${var.vm_ram}"
  generation             = 2

  snapshot_file_location = "${var.vm_path}\\${var.vm_hostname}\\snapshot"  
  static_memory          = true
  state                  = "Running"

  network_adaptors {
    name        = "defaultNetwork"
    switch_name = data.hyperv_network_switch.defaultNetwork.name
  }

  hard_disk_drives {
    path                = hyperv_vhd.vm_vhd.path
    controller_number   = "0"
    controller_location = "0"
  }

  integration_services = {
    VSS = true
  }
}
#===============================================================================
# hyperv server configuration
#===============================================================================

hyperv_server     = "WIN-MQHOQDEMMHK"
hyperv_serverPort = "5986"
hyperv_user       = "Administrator"
hyperv_password   = "P@ssw0rd"
hyperv_sslSkip    = "true"

#===============================================================================
# hyperv VN parameters
#===============================================================================
vm_templateName     = "Windows Server 2022(Template"
vm_path             = "D:\\VM"
vm_hostname     = "test"
vm_cpu              = "2"
vm_ram              = "2147483648" #2GB
vm_network          = "172.22.41.x"
vm_diskSize         = "32212254720"  #30GB
variables.tf
#====================#
# hyperv connection  #
#====================#

variable "hyperv_server" {
  description = "hyperv server"
  type        = string
}

variable "hyperv_serverPort" {
  description = "hyperv server Port"
  type        = string
}

variable "hyperv_user" {
  description = "hyperv username"
  type        = string
}

variable "hyperv_password" {
  description = "hyperv password"
  type        = string
  sensitive   = true
}

variable "hyperv_sslSkip" {
  description = "hyperv ssl Skip"
  type        = string
}

#=========================#
# hyperv virtual machine  #
#=========================#

variable "vm_templateName" {
  description = "vm templateName"
  type        = string
}

variable "vm_path" {
  description = "vm path folder"
  type        = string
}

variable "vm_hostname" {
  description = "vm hostname"
  type        = string
}

variable "vm_cpu" {
  description = "Number of vCPU for the hyperv virtual machines"
  type        = string
}

variable "vm_ram" {
  description = "Amount of RAM for the hyperv virtual machines (example: 2048)"
  type        = string
}

variable "vm_network" {
  description = "hyperv network name"
  type        = string
}

variable "vm_diskSize" {
  description = "vm diskSize"
  type        = string
}

Debug Output

│ Error: Provider produced inconsistent final plan
│
│ When expanding the plan for hyperv_machine_instance.vm_instance to include new values learned so far during apply, provider "registry.terraform.io/taliesins/hyperv" produced an invalid new value for
│ .hard_disk_drives[0].path: was cty.StringVal("D:\\VM\\test\\test.vhdx"), but now cty.StringVal("").
│
│ This is a bug in the provider, which should be reported in the provider's own issue tracker.

Expected Behavior

Based on the contents of your tf file, you expect the following results:

Clone the "Windows Server 2022" template to the directory "D:/VM/test" Create a file called "test.vhdx" Create a "hyperv_machine_instance" and reference the path to the "hyperv_vhd.vm_vhd.path" in the "hard_disk_drives" Finally, I should have a VM named "test", which is a clone of the "Windows Server 2022" template.

Actual Behavior

"hard_disk_drives" path not being able to read the correct variable value

Steps to Reproduce

  1. terraform apply

Here are the configurations I have made and my environment information. Please let me know if there is any other information I can provide.

BTW

BTW, the Requirements section on the project homepage mentions that Terraform version 1.29.x is needed. However, the latest version of Terraform is 1.4.6, so you may be referring to version 0.29.x instead, right? image

Wei-Yo commented 1 year ago

I am trying to narrow down the scope of the problem, but I am not sure if I am encountering more issues or if the root cause is the same.

For now, I am not using the "hyperv_machine_instance" resource and just observing what the "hyperv_vhd" resource can do for me. I replaced all path variables with their values and expected to clone the "Windows Server 2022" template to the "D:/VM/test" directory and create a file called "test.vhdx".

However, the execution result was unexpected, and the error message is as follows:

│ Error: [ERROR][hyperv][read] path argument is required
│
│   with hyperv_vhd.vm_vhd,
│   on main.tf line 38, in resource "hyperv_vhd" "vm_vhd":
│   38: resource "hyperv_vhd" "vm_vhd" {
│

During the execution process, I saw that the Windows Server 2022 template was being exported to the "D:/VM/test" directory on the Hyper-V host. However, every time the export reached 100% completion, the directory for the Windows Server 2022 template would disappear.

This also caused the error message to mention that it could not read the path for "hyperv_vhd.vm_vhd".

If you need me to provide any other details, please let me know.

Wei-Yo commented 1 year ago

I have another question. Can the current Hyper-V provider achieve functionality similar to vSphere's Customizing Guest Operating Systems? After successfully cloning a VM through a template, I want to use Terraform to set the hostname, IP, mask, and other settings for the VM's OS.

Is this possible?

data-tangles commented 1 year ago

The provider should be able to set Guest OS parameters however the provider would need to be updated for this. In the meantime you could use something like Ansible and Packer to achieve this.

Before I started using this provider I was using Ansible to build Hyper-V VM's. Using Hashicorp Packer you could set static IP's in the autounattend.xml file and then use Ansible to connect to and configure the VM

MichaelCade commented 1 month ago

I have just hit this same issue, was there any work around or progress made