Repository: ansible/ansible-modules-core

Issue:
vsphere_guest module: cluster parameter not optional when deploying from template
##### Issue Type:

Bug Report
##### Ansible Version:

```
$ ansible --version
ansible 1.9 (devel b11be68249) last updated 2015/03/16 22:21:38 (GMT -400)
  lib/ansible/modules/core: (detached HEAD 8658b82de7) last updated 2015/03/16 22:22:58 (GMT -400)
  lib/ansible/modules/extras: (detached HEAD 696bc60caa) last updated 2015/03/16 22:23:01 (GMT -400)
  v2/ansible/modules/core: (detached HEAD 34784b7a61) last updated 2015/03/16 22:23:04 (GMT -400)
  v2/ansible/modules/extras: (detached HEAD 46e316a20a) last updated 2015/03/16 22:23:07 (GMT -400)
  configured module search path = None
```
##### Environment:

N/A
##### Summary:

The cluster parameter should be optional when deploying a guest from a template. For example, with a standalone ESXi host.
##### Steps To Reproduce:

Playbook example below.

```

---
- hosts: localhost
  tasks:
    - name: deploy new vm from template
    - vsphere_guest:
          vcenter_hostname: "{{ esxi_hostname }}"
          username: "{{ esxi_username }}"
          password: "{{ esxi_password }}"
          guest: newvm001
          from_template: yes
          template_src: "{{ esxi_template }}"
          resource_pool: "{{ esxi_pool }}"
```
##### Expected Results:

The task should be executed successfully without the need of a cluster parameter.
##### Actual Results:

```
TASK: [deploy new vm from template] ***********************************************
failed: [localhost] => {"failed": true}
msg: parameters are required together: ['resource_pool', 'cluster']

FATAL: all hosts have already failed -- aborting
```



Discussion:
I now have a cluster in my environment, but no resource pools. In fact, I can't create resource pools because I can't turn on vSphere DRS (Enterprise or Enterprise Plus license is required).

In short, the resource pool should also be optional. I can't deploy a guest from a template because of that.

@bcoca This should be labeled as feature_idea, not docs_report.

there is an implicit cluster and resource pool you can use in all cases, we should make that clear in the docs to avoid confusion. To be really nice, we should default to those when needed.

@bcoca Thanks, I actually noticed that "/Resources" is the implicit resource pool if none exists. I don't know about an implicit cluster however.

@bcoca what is the implicit cluster?  In the documentation example they have "MainCluster" - this does not seem to work. Thanks

@bcoca @cicino The "MainCluster" option isn't working for me either and it would be very nice to be able to provision this way.

@bcoca Actually this affects me too. The only required parameter to the CloneVM_Task as used by the pysphere vm.clone method is a resource pool MOR. However on environments where no clusters are configured but there are multiple ESXi hosts under the management of a single vCenter Server you cant use the template deployment function. As far as I can see we could have the option for specifying datacenter and esxi host instead of a cluster. 


Resolving patch:
diff --git a/cloud/vmware/vsphere_guest.py b/cloud/vmware/vsphere_guest.py
--- a/cloud/vmware/vsphere_guest.py
+++ b/cloud/vmware/vsphere_guest.py
@@ -526,22 +526,74 @@ def deploy_template(vsphere_client, guest, resource_pool, template_src, esxi, mo
     vmTemplate = vsphere_client.get_vm_by_name(template_src)
     vmTarget = None
 
-    try:
-        cluster = [k for k,
-                   v in vsphere_client.get_clusters().items() if v == cluster_name][0]
-    except IndexError, e:
-        vsphere_client.disconnect()
-        module.fail_json(msg="Cannot find Cluster named: %s" %
-                         cluster_name)
+    if esxi:
+        datacenter = esxi['datacenter']
+        esxi_hostname = esxi['hostname']
+
+        # Datacenter managed object reference
+        dclist = [k for k,
+                 v in vsphere_client.get_datacenters().items() if v == datacenter]
+        if dclist:
+            dcmor=dclist[0]
+        else:
+            vsphere_client.disconnect()
+            module.fail_json(msg="Cannot find datacenter named: %s" % datacenter)
 
-    try:
-        rpmor = [k for k, v in vsphere_client.get_resource_pools(
-            from_mor=cluster).items()
-            if v == resource_pool][0]
-    except IndexError, e:
-        vsphere_client.disconnect()
-        module.fail_json(msg="Cannot find Resource Pool named: %s" %
-                         resource_pool)
+        dcprops = VIProperty(vsphere_client, dcmor)
+
+        # hostFolder managed reference
+        hfmor = dcprops.hostFolder._obj
+
+        # Grab the computerResource name and host properties
+        crmors = vsphere_client._retrieve_properties_traversal(
+            property_names=['name', 'host'],
+            from_node=hfmor,
+            obj_type='ComputeResource')
+
+        # Grab the host managed object reference of the esxi_hostname
+        try:
+            hostmor = [k for k,
+                       v in vsphere_client.get_hosts().items() if v == esxi_hostname][0]
+        except IndexError, e:
+            vsphere_client.disconnect()
+            module.fail_json(msg="Cannot find esx host named: %s" % esxi_hostname)
+
+        # Grab the computeResource managed object reference of the host we are
+        # creating the VM on.
+        crmor = None
+        for cr in crmors:
+            if crmor:
+                break
+            for p in cr.PropSet:
+                if p.Name == "host":
+                    for h in p.Val.get_element_ManagedObjectReference():
+                        if h == hostmor:
+                            crmor = cr.Obj
+                            break
+                    if crmor:
+                        break
+        crprops = VIProperty(vsphere_client, crmor)
+
+        rpmor = crprops.resourcePool._obj
+    elif resource_pool:
+        try:
+            cluster = [k for k,
+                       v in vsphere_client.get_clusters().items() if v == cluster_name][0]
+        except IndexError, e:
+            vsphere_client.disconnect()
+            module.fail_json(msg="Cannot find Cluster named: %s" %
+                             cluster_name)
+
+        try:
+            rpmor = [k for k, v in vsphere_client.get_resource_pools(
+                from_mor=cluster).items()
+                if v == resource_pool][0]
+        except IndexError, e:
+            vsphere_client.disconnect()
+            module.fail_json(msg="Cannot find Resource Pool named: %s" %
+                             resource_pool)
+    else:
+        module.fail_json(msg="You need to specify either esxi:[datacenter,hostname] or [cluster,resource_pool]")
 
     try:
         vmTarget = vsphere_client.get_vm_by_name(guest)


Test patch: