# Buggy code
def configure_network(self, vm_obj):
    # Ignore empty networks, this permits to keep networks when deploying a template/cloning a VM
    if len(self.params["networks"]) == 0:
        return

    network_devices = list()
    for network in self.params["networks"]:
        if "ip" in network or "netmask" in network:
            if "ip" not in network or "netmask" not in network:
                self.module.fail_json(
                    msg="Both 'ip' and 'netmask' are required together."
                )

        if "name" in network:
            if find_obj(self.content, [vim.Network], network["name"]) is None:
                self.module.fail_json(
                    msg="Network '%(name)s' does not exists" % network
                )

        elif "vlan" in network:
            dvps = self.cache.get_all_objs(
                self.content, [vim.dvs.DistributedVirtualPortgroup]
            )
            for dvp in dvps:
                if (
                    hasattr(dvp.config.defaultPortConfig, "vlan")
                    and dvp.config.defaultPortConfig.vlan.vlanId == network["vlan"]
                ):
                    network["name"] = dvp.config.name
                    break
                if dvp.config.name == network["vlan"]:
                    network["name"] = dvp.config.name
                    break
            else:
                self.module.fail_json(msg="VLAN '%(vlan)s' does not exist" % network)
        else:
            self.module.fail_json(msg="You need to define a network name or a vlan")

        network_devices.append(network)

    # List current device for Clone or Idempotency
    current_net_devices = self.get_vm_network_interfaces(vm=vm_obj)
    if len(network_devices) < len(current_net_devices):
        self.module.fail_json(
            msg="given network device list is lesser than current VM device list (%d < %d). "
            "Removing interfaces is not allowed"
            % (len(network_devices), len(current_net_devices))
        )

    for key in range(0, len(network_devices)):
        # Default device type is vmxnet3, VMWare best practice
        device_type = network_devices[key].get("device_type", "vmxnet3")
        nic = self.device_helper.create_nic(
            device_type, "Network Adapter %s" % (key + 1), network_devices[key]
        )

        nic_change_detected = False
        if key < len(current_net_devices) and (vm_obj or self.params["template"]):
            nic.operation = vim.vm.device.VirtualDeviceSpec.Operation.edit
            # Changing mac address has no effect when editing interface
            if (
                "mac" in network_devices[key]
                and nic.device.macAddress != current_net_devices[key].macAddress
            ):
                self.module.fail_json(
                    msg="Changing MAC address has not effect when interface is already present. "
                    "The failing new MAC address is %s" % nic.device.macAddress
                )

            nic.device = current_net_devices[key]
            nic.device.deviceInfo = vim.Description()
        else:
            nic.operation = vim.vm.device.VirtualDeviceSpec.Operation.add
            nic_change_detected = True

        if hasattr(self.cache.get_network(network_devices[key]["name"]), "portKeys"):
            # VDS switch
            pg_obj = find_obj(
                self.content,
                [vim.dvs.DistributedVirtualPortgroup],
                network_devices[key]["name"],
            )

            if nic.device.backing and (
                nic.device.backing.port.portgroupKey != pg_obj.key
                or nic.device.backing.port.switchUuid
                != pg_obj.config.distributedVirtualSwitch.uuid
            ):
                nic_change_detected = True

            dvs_port_connection = vim.dvs.PortConnection()
            dvs_port_connection.portgroupKey = pg_obj.key
            dvs_port_connection.switchUuid = pg_obj.config.distributedVirtualSwitch.uuid
            nic.device.backing = (
                vim.vm.device.VirtualEthernetCard.DistributedVirtualPortBackingInfo()
            )
            nic.device.backing.port = dvs_port_connection
            nic_change_detected = True
        else:
            # vSwitch
            if not isinstance(
                nic.device.backing, vim.vm.device.VirtualEthernetCard.NetworkBackingInfo
            ):
                nic.device.backing = (
                    vim.vm.device.VirtualEthernetCard.NetworkBackingInfo()
                )
                nic_change_detected = True

            net_obj = self.cache.get_network(network_devices[key]["name"])
            if nic.device.backing.network != net_obj:
                nic.device.backing.network = net_obj
                nic_change_detected = True

            if nic.device.backing.deviceName != network_devices[key]["name"]:
                nic.device.backing.deviceName = network_devices[key]["name"]
                nic_change_detected = True

        if nic_change_detected:
            self.configspec.deviceChange.append(nic)
            self.change_detected = True


# Traceback (AttributeError)
The full traceback is:
Traceback (most recent call last):
File "/tmp/ansible_n6hEeJ/ansible_module_vmware_guest.py", line 1503, in <module>
main()
File "/tmp/ansible_n6hEeJ/ansible_module_vmware_guest.py", line 1479, in main
result = pyv.reconfigure_vm()
File "/tmp/ansible_n6hEeJ/ansible_module_vmware_guest.py", line 1351, in reconfigure_vm
self.configure_network(vm_obj=self.current_vm_obj)
File "/tmp/ansible_n6hEeJ/ansible_module_vmware_guest.py", line 727, in configure_network
(nic.device.backing.port.portgroupKey != pg_obj.key or
AttributeError: 'vim.vm.device.VirtualEthernetCard.NetworkBackingIn' object has no attribute 'port'

fatal: [localhost]: FAILED! => {
"changed": false,
"failed": true,
"module_stderr": "Traceback (most recent call last):\n  File \"/tmp/ansible_n6hEeJ/ansible_module_vmware_guest.py\", line 1503, in <module>\n    main()\n  File \"/tmp/ansible_n6hEeJ/ansible_module_vmware_guest.py\", line 1479, in main\n    result = pyv.reconfigure_vm()\n  File \"/tmp/ansible_n6hEeJ/ansible_module_vmware_guest.py\", line 1351, in reconfigure_vm\n    self.configure_network(vm_obj=self.current_vm_obj)\n  File \"/tmp/ansible_n6hEeJ/ansible_module_vmware_guest.py\", line 727, in configure_network\n    (nic.device.backing.port.portgroupKey != pg_obj.key or\nAttributeError: 'vim.vm.device.VirtualEthernetCard.NetworkBackingIn' object has no attribute 'port'\n",
"module_stdout": "",
"msg": "MODULE FAILURE",
"rc": 0
}

# Fixed code
def configure_network(self, vm_obj):
    # Ignore empty networks, this permits to keep networks when deploying a template/cloning a VM
    if len(self.params["networks"]) == 0:
        return

    network_devices = list()
    for network in self.params["networks"]:
        if "ip" in network or "netmask" in network:
            if "ip" not in network or "netmask" not in network:
                self.module.fail_json(
                    msg="Both 'ip' and 'netmask' are required together."
                )

        if "name" in network:
            if find_obj(self.content, [vim.Network], network["name"]) is None:
                self.module.fail_json(
                    msg="Network '%(name)s' does not exists" % network
                )

        elif "vlan" in network:
            dvps = self.cache.get_all_objs(
                self.content, [vim.dvs.DistributedVirtualPortgroup]
            )
            for dvp in dvps:
                if (
                    hasattr(dvp.config.defaultPortConfig, "vlan")
                    and dvp.config.defaultPortConfig.vlan.vlanId == network["vlan"]
                ):
                    network["name"] = dvp.config.name
                    break
                if dvp.config.name == network["vlan"]:
                    network["name"] = dvp.config.name
                    break
            else:
                self.module.fail_json(msg="VLAN '%(vlan)s' does not exist" % network)
        else:
            self.module.fail_json(msg="You need to define a network name or a vlan")

        network_devices.append(network)

    # List current device for Clone or Idempotency
    current_net_devices = self.get_vm_network_interfaces(vm=vm_obj)
    if len(network_devices) < len(current_net_devices):
        self.module.fail_json(
            msg="given network device list is lesser than current VM device list (%d < %d). "
            "Removing interfaces is not allowed"
            % (len(network_devices), len(current_net_devices))
        )

    for key in range(0, len(network_devices)):
        # Default device type is vmxnet3, VMWare best practice
        device_type = network_devices[key].get("device_type", "vmxnet3")
        nic = self.device_helper.create_nic(
            device_type, "Network Adapter %s" % (key + 1), network_devices[key]
        )

        nic_change_detected = False
        if key < len(current_net_devices) and (vm_obj or self.params["template"]):
            nic.operation = vim.vm.device.VirtualDeviceSpec.Operation.edit
            # Changing mac address has no effect when editing interface
            if (
                "mac" in network_devices[key]
                and nic.device.macAddress != current_net_devices[key].macAddress
            ):
                self.module.fail_json(
                    msg="Changing MAC address has not effect when interface is already present. "
                    "The failing new MAC address is %s" % nic.device.macAddress
                )

            nic.device = current_net_devices[key]
            nic.device.deviceInfo = vim.Description()
        else:
            nic.operation = vim.vm.device.VirtualDeviceSpec.Operation.add
            nic_change_detected = True

        if hasattr(self.cache.get_network(network_devices[key]["name"]), "portKeys"):
            # VDS switch
            pg_obj = find_obj(
                self.content,
                [vim.dvs.DistributedVirtualPortgroup],
                network_devices[key]["name"],
            )

            if nic.device.backing and not hasattr(nic.device.backing, "port"):
                nic_change_detected = True
            elif nic.device.backing and (
                nic.device.backing.port.portgroupKey != pg_obj.key
                or nic.device.backing.port.switchUuid
                != pg_obj.config.distributedVirtualSwitch.uuid
            ):
                nic_change_detected = True

            dvs_port_connection = vim.dvs.PortConnection()
            dvs_port_connection.portgroupKey = pg_obj.key
            dvs_port_connection.switchUuid = pg_obj.config.distributedVirtualSwitch.uuid
            nic.device.backing = (
                vim.vm.device.VirtualEthernetCard.DistributedVirtualPortBackingInfo()
            )
            nic.device.backing.port = dvs_port_connection
            nic_change_detected = True
        else:
            # vSwitch
            if not isinstance(
                nic.device.backing, vim.vm.device.VirtualEthernetCard.NetworkBackingInfo
            ):
                nic.device.backing = (
                    vim.vm.device.VirtualEthernetCard.NetworkBackingInfo()
                )
                nic_change_detected = True

            net_obj = self.cache.get_network(network_devices[key]["name"])
            if nic.device.backing.network != net_obj:
                nic.device.backing.network = net_obj
                nic_change_detected = True

            if nic.device.backing.deviceName != network_devices[key]["name"]:
                nic.device.backing.deviceName = network_devices[key]["name"]
                nic_change_detected = True

        if nic_change_detected:
            self.configspec.deviceChange.append(nic)
            self.change_detected = True