VMware cannot customize MAC address

When replacing a VM with another VM, we would like to gather the MAC address of the old VM, delete that VM, create a new VM, and re-use the MAC address for the new VM.

The playbook happily creates a new VM but it will not customize the MAC address. We took a step back and tried just updating the MAC address on an existing VM, using a hardcoded MAC address instead of trying to pick up a variable and setting state to present so the VM won’t be powered on. The task succeeds, but we still don’t get the MAC address we want.

If I run it with -v, the output of the task clearly shows the automatically-assigned MAC address:

{
  "changed": true,
  "instance": {
    "module_hw": true,
    "hw_name": "my-test",
    "hw_power_status": "poweredOff",
. . . 
    "hw_processor_count": 2,
    "hw_cores_per_socket": 1,
    "hw_memtotal_mb": 8192,
    "hw_interfaces": [
      "eth0"
    ],
. . . 
    "hw_eth0": {
      "addresstype": "assigned",
      "label": "Network adapter 1",
      "macaddress": "00:33:44:uv:wx:yz", # redacted, not a real MAC address
      "ipaddresses": null,
      "summary": "Virtual Machine Network",
    },

Even though the invocation clearly shows the MAC address we want to apply:

  "invocation": {
    "module_args": {
      "hostname": "redacted",
      "username": "redacted",
. . . 
      "name": "my-test",
      "state": "present",
. . . 
  }
      ],
      "networks": [
        {
          "name": "Our Fancy Network",
          "mac": "00:11:22:ab:cd:ef", # redacted, not a real MAC address, but not the same as the one above
          "type": "dhcp"
        }
      ],

If I manually log into vSphere I have to open Edit Settings, then change from Automatic to Manual in the Network section before I can update the MAC address - is there an equivalent flag in the Ansible module I need to set?

I hope someone out there has pointers for me!

Thanks!

I assume you’re using community.vmware.vmware_guest_network module to perform this ?
If you could share your playbook/part of playbook where you’re trying to change the mac address

Sure! Thanks for the quick response.

The playbook currently has a single task. Here’s what it looks like:

    - name: Create a VM with specific MAC address
      community.vmware.vmware_guest:
        hostname: "{{ vcenter_hostname }}"
        username: "{{ vcenter_username }}"
        password: "{{ vcenter_password }}"
        validate_certs: false
        datacenter: "{{ vcenter_datacenter }}"
        cluster: "{{ vcenter_cluster }}"
        folder: /{{ vm_folder | default('dev-vms') }}
        name: re-use-mac
        state: present
        template: "{{ vm_template | default('template_2024')}}"
        disk:
          - size_gb: 30
            type: thin
            datastore: "{{ vm_info.datastore_url }}"
        hardware:
          memory_mb: "{{ vm_memory | default('8192') }}"
          num_cpus: "{{ vm_cpus | default('2') }}"
          num_cpu_cores_per_socket: "{{ vm_cpu_cores | default('1') }}"
          scsi: paravirtual
          version: latest
          boot_firmware: "efi"
        cdrom:
          - controller_number: 0
            unit_number: 0
            state: present
        networks:
          - name: "{{ vm_network | default('VM Network')}}"
            mac: "00:11:22:aa:bb:cc" # fake example mac address

Both playbook and task “succeed”. We do get a new VM, but we don’t get the MAC address.

We would be open to using the vmware.vmware or vmware.vmware_rest collections if that is the only (or best) way to accomplish what we need to do. We would just need to rebuild our EEs to make that happen.

thanks for sharing.

What if you try

    networks:
    - name: VM Network
      mac: 00:11:22:aa:bb:cc

I mean, for testing purpose, to set the name without using variable just to be sure if the result is the same or not.
According to the modules documentation there not using " " so give a try like this, if it works, we’ll check about setting variable properly :slight_smile:

I can confirm this. Here is a short example of my test playbook:

---
- hosts: all
  gather_facts: false

  tasks:
  - name: Provision VM
    community.vmware.vmware_guest:
      hostname: "{{ vm_vcenter }}"
      username: "{{ vm_vcenter_user | default(omit) }}"
      password: "{{ vm_vcenter_pass | default(omit) }}"
      validate_certs: false
      datacenter: "{{ vm_vmware_datacenter }}"
      cluster: "{{ vm_vmware_cluster }}"
      name: "vmware-guest-test-1"
      state: present
      folder: "/Test"
      networks:
      - name: "dhcp"
        mac: "9d:66:e3:f2:7c:ab"
      template: "{{ vm_template_name_default }}"
    delegate_to: localhost

VMware assigns random generated “00:50:56:x:x:x” address instead of explicitly specified one.

This is on ansible-core 2.16.7 and community.vmware 4.4.0.

On the other hand, this only happens when you provision VM from a template. If you are creating a VM from scratch, then it assigns specified MAC address but only during provisioning. It does not change MAC on already provisioned VM.

Here is a playbook for this second case:

---
- hosts: all
  gather_facts: false

  tasks:
  - name: Provision VM
    community.vmware.vmware_guest:
      hostname: "{{ vm_vcenter }}"
      username: "{{ vm_vcenter_user | default(omit) }}"
      password: "{{ vm_vcenter_pass | default(omit) }}"
      validate_certs: false
      datacenter: "{{ vm_vmware_datacenter }}"
      cluster: "{{ vm_vmware_cluster }}"
      name: "vmware-guest-test-1"
      state: present
      folder: "/Test"
      hardware:
        num_cpus: "2"
        memory_mb: "2048"
      disk:
      - datastore: "nvme-01"
        size: "10gb"
        type: "thin"
      networks:
      - name: "dhcp"
        mac: "9d:66:e3:f2:7c:ab"
      guest_id: "ubuntu64Guest"
    delegate_to: localhost

@acozine unfortunately, this seems to be a bug or at least an undocumented behavior. Definitely unexpected. You will have to file a bug report (issue) for community.vmware on GitHub with steps to reproduce.

There are a few similar issues on GitHub but from 2019. but have been fixed since. Maybe there was some regression at some point.

I feel a bit better after getting confirmation that it’s a bug. I will file a ticket on the collection repo.

I’m also going to try adding a task or two to my playbook to see if I can use community.vmware.vmware_guest_network to change the MAC address after the VM has been created. It’s not the most elegant solution, but if I can get it working it will be a useful workaround. The docs for that module suggest that mac should be used to identify an existing NIC, and it’s not clear if you can use it to replace a MAC address, but I can probably add a new NIC, set the MAC address, then delete the automatically-generated NIC . . .

Interestingly, in the first version of the vmware_guest_network module, you could pass either mac or manual_mac. The docs said:

manual_mac (string): Manual specified MAC address of the network adapter when creating, or reconfiguring. If not specified when creating new network adapter, mac address will be generated automatically. When reconfigure MAC address, VM should be in powered off state.

That option was either removed, or is no longer documented.

I implemented the workaround idea - you can create the VM from a template, give it a second NIC with the MAC address you want, power the VM down, delete the NIC with the automatically-assigned MAC address, and then power the VM back up. This is clunky, but at least it works, and the resulting VM is based on the template.

Ticket: vmware_guest module does not assign custom MAC address if building a VM from a template · Issue #2124 · ansible-collections/community.vmware · GitHub