josenk / terraform-provider-esxi

Terraform-provider-esxi plugin
GNU General Public License v3.0
540 stars 154 forks source link

How to get mac_address from a network_interfaces? #166

Closed jremerich closed 2 years ago

jremerich commented 2 years ago

Hi!

It's possible to get the generated network_interfaces's mac_address?

Here what I'm doing (look at local-exec):

terraform {
  required_version = ">= 0.13"
  required_providers {
    esxi = {
      source = "registry.terraform.io/josenk/esxi"
    }
  }
}

data "template_file" "userdata" {
  template = file("${path.module}/userdata.tpl")
  vars = {
    HOSTNAME   = var.name,
    IP         = var.ip,
    VLAN       = var.vlan,
    PUBLIC_KEY = file("~/.ssh/id_rsa.pub")
  }
}

resource "esxi_guest" "vms" {
  guest_name     = "${var.name}${var.ip}"
  disk_store     = var.disk_store
  boot_disk_type = "thin"
  boot_disk_size = var.disksize
  memsize        = var.memsize
  numvcpus       = var.numvcpus
  power          = "on"
  virthwver      = "14"
  guestos        = "centos8-64"

  guestinfo = {
    "userdata.encoding" = "gzip+base64"
    "userdata"          = base64gzip(data.template_file.userdata.rendered)
  }

  provisioner "local-exec" {
    command = "echo \"${self.network_interfaces[0].virtual_network} - ${self.network_interfaces[0].mac_address}\" >> ${path.module}/../../networks.txt"
  }

  ovf_source = "/home/zero/Server/labs/packer/centos/output-vmware/packer-vmware.ova"

  network_interfaces {
    virtual_network = var.networkGeneral
  }

  network_interfaces {
    virtual_network = var.networkFiber
  }

  network_interfaces {
    virtual_network = var.networkRedis
  }

  guest_startup_timeout  = 120
}

The VM is created successfuly. The file networks.txt is created too but just shows the network name on it:

VM Network - 

I want to get the mac_address to perform a more precise proccess to set fixed IP on VM. I'm creating a CentOS 8 and the network session on cloud-init doesn't work because CentOS doesn't support netplan.

Thanks!

josenk commented 2 years ago

I did a quick test and was able to re-create your problem...

I added this to my main.tf to see what exactly the provider collects.

output "mac" {
  value = esxi_guest.vms.network_interfaces.*
}

After the apply, the interesting thing is that the mac_address is missing...

I took a quick look at the code and found out why.

https://github.com/josenk/terraform-provider-esxi/blob/master/esxi/guest-read.go#L231-L237

As you can see, I actually had the code (which has been remarked out) to get the generated mac address, but it seems to break something else. I would have to do a deepdive into that issue because I don't really remember what the issue was???

Essentially, the generated mac addresses are not captured by the provider because it might change... As a work-around, you can generate a random mac using other providers (Something like this: https://registry.terraform.io/providers/ivoronin/macaddress/latest/docs/resources/macaddress). I tested it and it works as you require (outputs now show the mac_address and networks.txt is created with the mac_address).

resource "macaddress" "mac1" {
    # https://docs.vmware.com/en/VMware-vSphere/7.0/com.vmware.vsphere.networking.doc/GUID-F9243FED-F081-498F-B4A9-EF950292AF77.html
    prefix = [0, 80, 86]
}
resource "macaddress" "mac2" {
    # https://docs.vmware.com/en/VMware-vSphere/7.0/com.vmware.vsphere.networking.doc/GUID-F9243FED-F081-498F-B4A9-EF950292AF77.html
    prefix = [0, 80, 86]
}
resource "macaddress" "mac3" {
    # https://docs.vmware.com/en/VMware-vSphere/7.0/com.vmware.vsphere.networking.doc/GUID-F9243FED-F081-498F-B4A9-EF950292AF77.html
    prefix = [0, 80, 86]
}

<<< SNIP >>>
  network_interfaces {
    virtual_network = var.networkGeneral
    mac_address     = macaddress.mac1.address
  }

  network_interfaces {
    virtual_network = var.networkFiber
    mac_address     = macaddress.mac2.address
  }

  network_interfaces {
    virtual_network = var.networkRedis
    mac_address     = macaddress.mac3.address
  }
}

output "mac" {
  value = esxi_guest.vms.network_interfaces.*
}

You should really validate this to make sure it meets your needs... I did this simply as a test. YMMV

jremerich commented 2 years ago

@josenk Thanks! Setting a static mac_address works and now I can capture this information.

But it is causing an error on power the vm on showing on ESXi UI this message: Impermissible static Ethernet address: '00:50:56:9c:62:7e'. It conflicts with VMware reserved MACs.

I'd some research and find out that needs to add on VMX file the option ethernetN.CheckMACAddress = "FALSE", so I looked on your code that the option isn't write on vmx file, look:

https://github.com/josenk/terraform-provider-esxi/blob/d0a59254384fcf04d1399844733686ad65934cae/esxi/guest_functions.go#L310-L316

I'd it manually and execute the reload and power.on commands following the log and the vm powered on successfully.

Unfortunately I have no experience in Golang, otherwise I would do a PR.

Thanks for your attention and by this tool.