Repository: ansible-collections/community.vmware

Issue:
vmware_guest_network - Adding NICS to VM Fails if VM has never been powered on
##### SUMMARY
https://github.com/ansible-collections/community.vmware/blob/70d752bc4419e6f1c74d9faee21793376f9899b8/plugins/modules/vmware_guest_network.py#L470
This fails if the VM has never been powered on before (i.e you deployed a VM from an OVA and want to add nics before powering on for the first time)

##### ISSUE TYPE
- Bug Report

##### COMPONENT NAME
- vmware_guest_network

##### ANSIBLE VERSION
```
ansible 2.9.19
  config file = /etc/ansible/ansible.cfg
  configured module search path = ['/home/server.local/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python3.6/site-packages/ansible
  executable location = /usr/bin/ansible
  python version = 3.6.8 (default, Aug 18 2020, 08:33:21) [GCC 8.3.1 20191121 (Red Hat 8.3.1-5)]
```

##### CONFIGURATION
No changes from default

##### OS / ENVIRONMENT
RHEL 8.3
Tower 3.7.1

##### STEPS TO REPRODUCE
- deploy any OVA without powering on
- use `community.vmware.vmware_guest_network` to add nics

##### EXPECTED RESULTS
NICS added to VM successfully

##### ACTUAL RESULTS
```
{
    "module_stdout": "Traceback (most recent call last):\r\n  File \"/root/.ansible/tmp/ansible-tmp-1622083361.5219777-46-219301060242623/AnsiballZ_vmware_guest_network.py\", line 102, in <module>\r\n    _ansiballz_main()\r\n  File \"/root/.ansible/tmp/ansible-tmp-1622083361.5219777-46-219301060242623/AnsiballZ_vmware_guest_network.py\", line 94, in _ansiballz_main\r\n    invoke_module(zipped_mod, temp_path, ANSIBALLZ_PARAMS)\r\n  File \"/root/.ansible/tmp/ansible-tmp-1622083361.5219777-46-219301060242623/AnsiballZ_vmware_guest_network.py\", line 40, in invoke_module\r\n    runpy.run_module(mod_name='ansible_collections.community.vmware.plugins.modules.vmware_guest_network', init_globals=None, run_name='__main__', alter_sys=True)\r\n  File \"/usr/lib64/python3.6/runpy.py\", line 205, in run_module\r\n    return _run_module_code(code, init_globals, run_name, mod_spec)\r\n  File \"/usr/lib64/python3.6/runpy.py\", line 96, in _run_module_code\r\n    mod_name, mod_spec, pkg_name, script_name)\r\n  File \"/usr/lib64/python3.6/runpy.py\", line 85, in _run_code\r\n    exec(code, run_globals)\r\n  File \"/tmp/ansible_community.vmware.vmware_guest_network_payload_lgz6j7e9/ansible_community.vmware.vmware_guest_network_payload.zip/ansible_collections/community/vmware/plugins/modules/vmware_guest_network.py\", line 890, in <module>\r\n  File \"/tmp/ansible_community.vmware.vmware_guest_network_payload_lgz6j7e9/ansible_community.vmware.vmware_guest_network_payload.zip/ansible_collections/community/vmware/plugins/modules/vmware_guest_network.py\", line 879, in main\r\n  File \"/tmp/ansible_community.vmware.vmware_guest_network_payload_lgz6j7e9/ansible_community.vmware.vmware_guest_network_payload.zip/ansible_collections/community/vmware/plugins/modules/vmware_guest_network.py\", line 711, in _nic_present\r\n  File \"/tmp/ansible_community.vmware.vmware_guest_network_payload_lgz6j7e9/ansible_community.vmware.vmware_guest_network_payload.zip/ansible_collections/community/vmware/plugins/modules/vmware_guest_network.py\", line 470, in _get_nics_from_vm\r\nTypeError: '<' not supported between instances of 'NoneType' and 'NoneType'\r\n",
    "module_stderr": "Shared connection to 10.60.253.13 closed.\r\n",
    "exception": "Traceback (most recent call last):\r\n  File \"/root/.ansible/tmp/ansible-tmp-1622083361.5219777-46-219301060242623/AnsiballZ_vmware_guest_network.py\", line 102, in <module>\r\n    _ansiballz_main()\r\n  File \"/root/.ansible/tmp/ansible-tmp-1622083361.5219777-46-219301060242623/AnsiballZ_vmware_guest_network.py\", line 94, in _ansiballz_main\r\n    invoke_module(zipped_mod, temp_path, ANSIBALLZ_PARAMS)\r\n  File \"/root/.ansible/tmp/ansible-tmp-1622083361.5219777-46-219301060242623/AnsiballZ_vmware_guest_network.py\", line 40, in invoke_module\r\n    runpy.run_module(mod_name='ansible_collections.community.vmware.plugins.modules.vmware_guest_network', init_globals=None, run_name='__main__', alter_sys=True)\r\n  File \"/usr/lib64/python3.6/runpy.py\", line 205, in run_module\r\n    return _run_module_code(code, init_globals, run_name, mod_spec)\r\n  File \"/usr/lib64/python3.6/runpy.py\", line 96, in _run_module_code\r\n    mod_name, mod_spec, pkg_name, script_name)\r\n  File \"/usr/lib64/python3.6/runpy.py\", line 85, in _run_code\r\n    exec(code, run_globals)\r\n  File \"/tmp/ansible_community.vmware.vmware_guest_network_payload_lgz6j7e9/ansible_community.vmware.vmware_guest_network_payload.zip/ansible_collections/community/vmware/plugins/modules/vmware_guest_network.py\", line 890, in <module>\r\n  File \"/tmp/ansible_community.vmware.vmware_guest_network_payload_lgz6j7e9/ansible_community.vmware.vmware_guest_network_payload.zip/ansible_collections/community/vmware/plugins/modules/vmware_guest_network.py\", line 879, in main\r\n  File \"/tmp/ansible_community.vmware.vmware_guest_network_payload_lgz6j7e9/ansible_community.vmware.vmware_guest_network_payload.zip/ansible_collections/community/vmware/plugins/modules/vmware_guest_network.py\", line 711, in _nic_present\r\n  File \"/tmp/ansible_community.vmware.vmware_guest_network_payload_lgz6j7e9/ansible_community.vmware.vmware_guest_network_payload.zip/ansible_collections/community/vmware/plugins/modules/vmware_guest_network.py\", line 470, in _get_nics_from_vm\r\nTypeError: '<' not supported between instances of 'NoneType' and 'NoneType'\r\n",
    "msg": "MODULE FAILURE\nSee stdout/stderr for the exact error",
    "rc": 1,
    "_ansible_no_log": false,
    "changed": false,
    "item": "PACS-RTR-Trunk",
    "ansible_loop_var": "item",
    "_ansible_item_label": "PACS-RTR-Trunk"
}
```


Discussion:
Files identified in the description:
* [`lib/ansible/plugins/connection`](https://github.com/['ansible-collections/amazon.aws', 'ansible-collections/community.aws', 'ansible-collections/community.vmware']/blob/main/lib/ansible/plugins/connection)
* [`plugins/modules/vmware_guest_snapshot.py`](https://github.com/['ansible-collections/amazon.aws', 'ansible-collections/community.aws', 'ansible-collections/community.vmware']/blob/main/plugins/modules/vmware_guest_snapshot.py)

If these files are inaccurate, please update the `component name` section of the description or use the `!component` bot command.

[click here for bot help](https://github.com/ansible/ansibullbot/blob/master/ISSUE_HELP.md)
<!--- boilerplate: components_banner --->
@teamosceola: Greetings! Thanks for taking the time to open this issue. In order for the community to handle your issue effectively, we need a bit more information.

Here are the items we could not find in your description:
- ansible version

Please set the description of this issue with this template:
https://raw.githubusercontent.com/ansible/ansible/devel/.github/ISSUE_TEMPLATE/bug_report.md

[click here for bot help](https://github.com/ansible/ansibullbot/blob/master/ISSUE_HELP.md)
<!--- boilerplate: issue_missing_data --->
cc @Akasurde @Tomorrow9 @goneri @lparkes @nerzhul @pgbidkar @warthog9
[click here for bot help](https://github.com/ansible/ansibullbot/blob/master/ISSUE_HELP.md)
<!--- boilerplate: notify --->
Files identified in the description:
* [`plugins/modules/vmware_guest_network.py`](https://github.com/['ansible-collections/amazon.aws', 'ansible-collections/community.aws', 'ansible-collections/community.vmware']/blob/main/plugins/modules/vmware_guest_network.py)

If these files are inaccurate, please update the `component name` section of the description or use the `!component` bot command.

[click here for bot help](https://github.com/ansible/ansibullbot/blob/master/ISSUE_HELP.md)
<!--- boilerplate: components_banner --->
> https://github.com/ansible-collections/community.vmware/blob/70d752bc4419e6f1c74d9faee21793376f9899b8/plugins/modules/vmware_guest_network.py#L470

It looks like this has been introduced with PR #29. @acalm do you remember why you've sorted the NICs on the MAC address? Did you just want to have a nicely sorted list somewhere or is this needed for the module to work?
> > https://github.com/ansible-collections/community.vmware/blob/70d752bc4419e6f1c74d9faee21793376f9899b8/plugins/modules/vmware_guest_network.py#L470
> 
> It looks like this has been introduced with PR #29. @acalm do you remember why you've sorted the NICs on the MAC address? Did you just want to have a nicely sorted list somewhere or is this needed for the module to work?

@mariolenz I have some vague memory it's done due the diff looking messed up, but I can't remember really, it may just been me imagining some weird edge case where order mattered. From the exception it looks as if `nic.macAddress` is `None` in a deployed not-yet-powered-on OVA(?) I guess it would be possible to do something like `getattr(nic, 'macAddress', 'not_initialized')` [here](https://github.com/ansible-collections/community.vmware/blob/70d752bc4419e6f1c74d9faee21793376f9899b8/plugins/modules/vmware_guest_network.py#L433) or, just throw away line 470 and observe what happens further down the line, `mac_address` may be used for comparisons later in the code and break there instead, if not :tada: fixed forever :tada: :)
Thanks @teamosceola for reporting this. This issue is indeed pretty annoying. Should we revert #29 until we've got this fixed?
It looks like it was possible to compare `None` in Python 2, but [Python 3.0 changed the rules for ordering comparisons](https://docs.python.org/3/whatsnew/3.0.html#ordering-comparisons).

> Should we revert #29 until we've got this fixed?

I thought we could fix this by changeing the lambda function to:

```python
sorted(nic_info_lst, key=lambda d: d['mac_address'] if (d['mac_address'] is not None) else '00:00:00:00:00:00')
```

but I'm not sure if we don't run into another problem somewhere else if we have more than one new NIC without a MAC address. We could give it a try, though. I don't think it'll make things worse.

Resolving patch:
diff --git a/plugins/modules/vmware_guest_network.py b/plugins/modules/vmware_guest_network.py
--- a/plugins/modules/vmware_guest_network.py
+++ b/plugins/modules/vmware_guest_network.py
@@ -467,7 +467,7 @@ def _get_nics_from_vm(self, vm_obj):
 
             nic_info_lst.append(d_item)
 
-        nic_info_lst = sorted(nic_info_lst, key=lambda d: d['mac_address'])
+        nic_info_lst = sorted(nic_info_lst, key=lambda d: d['mac_address'] if (d['mac_address'] is not None) else '00:00:00:00:00:00')
         return nic_info_lst, nics
 
     def _get_compute_resource_by_name(self, recurse=True):


Test patch: