Repository: ansible-collections/community.vmware

Issue:
vmware_deploy_ovf - Failure validating OVF import spec: The provided network mapping between OVF networks and the system network is not supported by any host
<!--- Verify first that your issue is not already reported on GitHub -->
<!--- Also test if the latest release and devel branch are affected too -->
<!--- Complete *all* sections as described, this form is processed automatically -->

##### SUMMARY
I have a vCenter with 3 clusters configured and NSX-T on networking layer. The network is visible in all three clusters and deploying an ovf template in vCenter works just fine. But when using the vmware_deploy_ovf module an error "Failure validating OVF import spec: The provided network mapping between OVF networks and the system network is not supported by any host" is thrown. 

##### ISSUE TYPE
- Bug Report

##### COMPONENT NAME
vmware_deploy_ovf 

##### ANSIBLE VERSION
<!--- Paste verbatim output from "ansible --version" between quotes -->
```paste below
ansible 2.9.7
  config file = /etc/ansible/ansible.cfg
  configured module search path = [u'/home/ubuntu/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python2.7/dist-packages/ansible
  executable location = /usr/bin/ansible
  python version = 2.7.17 (default, Apr 15 2020, 17:20:14) [GCC 7.5.0]
```

##### CONFIGURATION
<!--- Paste verbatim output from "ansible-config dump --only-changed" between quotes -->
```paste below
ALLOW_WORLD_READABLE_TMPFILES(/etc/ansible/ansible.cfg) = False
DEFAULT_LOCAL_TMP(/etc/ansible/ansible.cfg) = /home/ubuntu/.ansible/tmp/ansible-local-5327JAdofg
HOST_KEY_CHECKING(/etc/ansible/ansible.cfg) = False
```

##### OS / ENVIRONMENT
<!--- Provide all relevant information below, e.g. target OS versions, network device firmware, etc. -->
Distributor ID: Ubuntu
Description:    Ubuntu 18.04.4 LTS
Release:        18.04
Codename:       bionic

vSphere / ESXi: 6.7
NSX-T: 2.5 

##### STEPS TO REPRODUCE
<!--- Describe exactly how to reproduce the problem, using a minimal test-case -->

<!--- Paste example playbooks or commands between quotes below -->
```yaml
- name: "Upload OVA to vSphere"
  vmware_deploy_ovf:
    hostname: '{{ vcenter.hostname }}'
    username: '{{ vcenter.username }}'
    password: '{{ vcenter.password }}'
    allow_duplicates: no
    fail_on_spec_warnings: no
    datacenter: '{{ vcenter.datacenter }}'
    cluster: '{{ vcenter.cluster }}'
    folder: '{{ vcenter.folder }}'
    datastore: '{{ vcenter.datastore }}'
    name: '{{ vcenter.vm_name }}'
    networks: "{u'VM Network':u'{{ vcenter.provisioning_network_label }}'}"
    validate_certs: no
    power_on: yes
    wait: yes
    wait_for_ip_address: yes
    ovf: "{{ playbook_dir }}/files/{{ ovf.file_name }}"
    properties:
      public-keys: "{{ ssh_public }}"
  delegate_to: localhost
```

<!--- HINT: You can paste gist.github.com links for larger files -->

##### EXPECTED RESULTS
<!--- Describe what you expected to happen when running the steps above -->
VM created

##### ACTUAL RESULTS
<!--- Describe what actually happened. If possible run with extra verbosity (-vvvv) -->

<!--- Paste verbatim command output between quotes -->
```paste below

TASK [vm_deployment : Upload OVA to vSphere] *******************************************************************************************************
task path: /home/ubuntu/ansible-test/roles/vm_deployment/tasks/main.yml:114
<localhost> ESTABLISH LOCAL CONNECTION FOR USER: ubuntu
<localhost> EXEC /bin/sh -c 'echo ~ubuntu && sleep 0'
<localhost> EXEC /bin/sh -c '( umask 77 && mkdir -p "` echo /home/ubuntu/.ansible/tmp `"&& mkdir /home/ubuntu/.ansible/tmp/ansible-tmp-1588694515.02-7541-22608241707231 && echo ansible-tmp-1588694515.02-7541-22608241707231="` echo /home/ubuntu/.ansible/tmp/ansible-tmp-1588694515.02-7541-22608241707231 `" ) && sleep 0'
Using module_utils file /usr/lib/python2.7/dist-packages/ansible/module_utils/_text.py
Using module_utils file /usr/lib/python2.7/dist-packages/ansible/module_utils/vmware.py
Using module_utils file /usr/lib/python2.7/dist-packages/ansible/module_utils/six/__init__.py
Using module_utils file /usr/lib/python2.7/dist-packages/ansible/module_utils/urls.py
Using module_utils file /usr/lib/python2.7/dist-packages/ansible/module_utils/basic.py
Using module_utils file /usr/lib/python2.7/dist-packages/ansible/module_utils/common/_collections_compat.py
Using module_utils file /usr/lib/python2.7/dist-packages/ansible/module_utils/common/__init__.py
Using module_utils file /usr/lib/python2.7/dist-packages/ansible/module_utils/common/text/formatters.py
Using module_utils file /usr/lib/python2.7/dist-packages/ansible/module_utils/common/validation.py
Using module_utils file /usr/lib/python2.7/dist-packages/ansible/module_utils/common/text/converters.py
Using module_utils file /usr/lib/python2.7/dist-packages/ansible/module_utils/pycompat24.py
Using module_utils file /usr/lib/python2.7/dist-packages/ansible/module_utils/common/text/__init__.py
Using module_utils file /usr/lib/python2.7/dist-packages/ansible/module_utils/common/process.py
Using module_utils file /usr/lib/python2.7/dist-packages/ansible/module_utils/parsing/convert_bool.py
Using module_utils file /usr/lib/python2.7/dist-packages/ansible/module_utils/common/_utils.py
Using module_utils file /usr/lib/python2.7/dist-packages/ansible/module_utils/common/parameters.py
Using module_utils file /usr/lib/python2.7/dist-packages/ansible/module_utils/parsing/__init__.py
Using module_utils file /usr/lib/python2.7/dist-packages/ansible/module_utils/common/_json_compat.py
Using module_utils file /usr/lib/python2.7/dist-packages/ansible/module_utils/common/sys_info.py
Using module_utils file /usr/lib/python2.7/dist-packages/ansible/module_utils/common/file.py
Using module_utils file /usr/lib/python2.7/dist-packages/ansible/module_utils/common/collections.py
Using module_utils file /usr/lib/python2.7/dist-packages/ansible/module_utils/distro/__init__.py
Using module_utils file /usr/lib/python2.7/dist-packages/ansible/module_utils/distro/_distro.py
Using module file /usr/lib/python2.7/dist-packages/ansible/modules/cloud/vmware/vmware_deploy_ovf.py
<localhost> PUT /home/ubuntu/.ansible/tmp/ansible-local-7277QiTLT4/tmpYuJhyg TO /home/ubuntu/.ansible/tmp/ansible-tmp-1588694515.02-7541-22608241707231/AnsiballZ_vmware_deploy_ovf.py
<localhost> EXEC /bin/sh -c 'chmod u+x /home/ubuntu/.ansible/tmp/ansible-tmp-1588694515.02-7541-22608241707231/ /home/ubuntu/.ansible/tmp/ansible-tmp-1588694515.02-7541-22608241707231/AnsiballZ_vmware_deploy_ovf.py && sleep 0'
<localhost> EXEC /bin/sh -c '/usr/bin/python /home/ubuntu/.ansible/tmp/ansible-tmp-1588694515.02-7541-22608241707231/AnsiballZ_vmware_deploy_ovf.py && sleep 0'
<localhost> EXEC /bin/sh -c 'rm -f -r /home/ubuntu/.ansible/tmp/ansible-tmp-1588694515.02-7541-22608241707231/ > /dev/null 2>&1 && sleep 0'
fatal: [testhost -> localhost]: FAILED! => {
    "changed": false,
    "invocation": {
        "module_args": {
            "allow_duplicates": false,
            "cluster": "CLUSTER_01",
            "datacenter": "DC_01",
            "datastore": "Datastore_01,
            "deployment_option": null,
            "disk_provisioning": "thin",
            "fail_on_spec_warnings": false,
            "folder": "/DC_01/vm/TEST_VMS",
            "hostname": "xxx",
            "inject_ovf_env": false,
            "name": "testvm",
            "networks": {
                "VM Network": "INFRA-01"
            },
            "ovf": "/home/ubuntu/ansible-test/files/ubuntu-server-cloudimg-amd64-18.04.ova",
            "password": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER",
            "port": 443,
            "power_on": true,
            "proxy_host": null,
            "proxy_port": null,
            "resource_pool": "Resources",
            "username": "XXX",
            "validate_certs": false,
            "wait": true,
            "wait_for_ip_address": true
        }
    },
    "msg": "Failure validating OVF import spec: The provided network mapping between OVF networks and the system network is not supported by any host."
}
```

I played with the REST API, result for /rest/vcenter/network
```
{
  "name": "INFRA-01",
  "type": "OPAQUE_NETWORK",
  "network": "network-o2950"
}
{
  "name": "INFRA-01",
  "type": "OPAQUE_NETWORK",
  "network": "network-o2951"
}
{
  "name": "INFRA-01",
  "type": "OPAQUE_NETWORK",
  "network": "network-o2952"
}
```
From what I saw the module uses network-o2950 .


Discussion:
Any update on this ? I am also facing same issue. 
@mehmoodkha I wasn't able to resolve the issue with the vmware_deploy_ovf module. But I guess it's because we don't use a resource pool.
As a workaround, I switched to [govc](https://github.com/vmware/govmomi/tree/master/govc) using an explicit host. Now, the deployment of OVA/OVF works again.
Thanks @Onke.

My issue was on VMC.

I was able to get proper details from VMC. Once I did modification it did worked.

```
networks: "{u'nat':u'mynet'}"
```
cc @Akasurde @Tomorrow9 @goneri @lparkes @pgbidkar @warthog9
[click here for bot help](https://github.com/ansible/ansibullbot/blob/master/ISSUE_HELP.md)
<!--- boilerplate: notify --->
I also hit this issue when there are more than one datacenter in vCenter server, no issue if there is only one datacenter. I'll take a look at this later if there is no one looking at this issue. Thanks. 
> I also hit this issue when there are more than one datacenter in vCenter server, no issue if there is only one datacenter. I'll take a look at this later if there is no one looking at this issue. Thanks.

So, I'm having the same issue under the same scenario, more than one datacenter in vCenter server. Besides the govc workaround, there is any other option?
I hit this issue on vCenter Server with two clusters. Are there any updates?
This module calls `find_network_by_name` function at L389 but I think this function cannot find a network object when there are same network names.
This issue may be resolved if this function can find network object according to Cluster, Host or vSwitch name, I think.
Sorry for the late update, I'll take a look at this. Thanks.

Resolving patch:
diff --git a/plugins/module_utils/vmware.py b/plugins/module_utils/vmware.py
--- a/plugins/module_utils/vmware.py
+++ b/plugins/module_utils/vmware.py
@@ -216,7 +216,6 @@ def find_object_by_name(content, name, obj_type, folder=None, recurse=True):
 
 
 def find_cluster_by_name(content, cluster_name, datacenter=None):
-
     if datacenter and hasattr(datacenter, 'hostFolder'):
         folder = datacenter.hostFolder
     else:
@@ -303,8 +302,12 @@ def find_dvs_by_name(content, switch_name, folder=None):
     return find_object_by_name(content, switch_name, [vim.DistributedVirtualSwitch], folder=folder)
 
 
-def find_hostsystem_by_name(content, hostname):
-    return find_object_by_name(content, hostname, [vim.HostSystem])
+def find_hostsystem_by_name(content, hostname, datacenter=None):
+    if datacenter and hasattr(datacenter, 'hostFolder'):
+        folder = datacenter.hostFolder
+    else:
+        folder = content.rootFolder
+    return find_object_by_name(content, hostname, [vim.HostSystem], folder=folder)
 
 
 def find_resource_pool_by_name(content, resource_pool_name):
@@ -1384,16 +1387,17 @@ def get_all_hosts_by_cluster(self, cluster_name):
             return []
 
     # Hosts related functions
-    def find_hostsystem_by_name(self, host_name):
+    def find_hostsystem_by_name(self, host_name, datacenter=None):
         """
         Find Host by name
         Args:
             host_name: Name of ESXi host
+            datacenter: (optional) Datacenter of ESXi resides
 
         Returns: True if found
 
         """
-        return find_hostsystem_by_name(self.content, hostname=host_name)
+        return find_hostsystem_by_name(self.content, hostname=host_name, datacenter=datacenter)
 
     def get_all_host_objs(self, cluster_name=None, esxi_host_name=None):
         """
diff --git a/plugins/modules/vmware_deploy_ovf.py b/plugins/modules/vmware_deploy_ovf.py
--- a/plugins/modules/vmware_deploy_ovf.py
+++ b/plugins/modules/vmware_deploy_ovf.py
@@ -355,12 +355,13 @@ def get_objects(self):
             self.resource_pool = self.find_resource_pool_by_cluster(self.params['resource_pool'], cluster=cluster)
         # Or get ESXi host in datacenter if ESXi host configured
         elif self.params['esxi_hostname']:
-            host = self.find_hostsystem_by_name(self.params['esxi_hostname'])
+            host = self.find_hostsystem_by_name(self.params['esxi_hostname'], datacenter=self.datacenter)
             if host is None:
-                self.module.fail_json(msg="Unable to find host '%(esxi_hostname)s'" % self.params)
+                self.module.fail_json(msg="Unable to find host '%(esxi_hostname)s' in datacenter '%(datacenter)s'" % self.params)
             self.resource_pool = self.find_resource_pool_by_name(self.params['resource_pool'], folder=host.parent)
         else:
-            self.resource_pool = self.find_resource_pool_by_name(self.params['resource_pool'])
+            # For more than one datacenter env, specify 'folder' to datacenter hostFolder
+            self.resource_pool = self.find_resource_pool_by_name(self.params['resource_pool'], folder=self.datacenter.hostFolder)
 
         if not self.resource_pool:
             self.module.fail_json(msg="Resource pool '%(resource_pool)s' could not be located" % self.params)
@@ -383,7 +384,8 @@ def get_objects(self):
             self.datastore = self.find_datastore_by_name(self.params['datastore'], datacenter_name=self.datacenter)
 
         if self.datastore is None:
-            self.module.fail_json(msg="Datastore '%(datastore)s' could not be located on specified ESXi host or datacenter" % self.params)
+            self.module.fail_json(msg="Datastore '%(datastore)s' could not be located on specified ESXi host or"
+                                      " datacenter" % self.params)
 
         for key, value in self.params['networks'].items():
             network = find_network_by_name(self.content, value, datacenter_name=self.datacenter)


Test patch: