# Buggy code
def main():
    vm = None

    proto_vm_hardware = {
        "memory_mb": int,
        "num_cpus": int,
        "scsi": string_types,
        "osid": string_types,
    }

    proto_vm_disk = {
        "disk1": {"datastore": string_types, "size_gb": int, "type": string_types}
    }

    proto_vm_nic = {
        "nic1": {
            "type": string_types,
            "network": string_types,
            "network_type": string_types,
        }
    }

    proto_esxi = {"datacenter": string_types, "hostname": string_types}

    module = AnsibleModule(
        argument_spec=dict(
            vcenter_hostname=dict(type="str", default=os.environ.get("VMWARE_HOST")),
            username=dict(type="str", default=os.environ.get("VMWARE_USER")),
            password=dict(
                type="str", no_log=True, default=os.environ.get("VMWARE_PASSWORD")
            ),
            state=dict(
                required=False,
                choices=[
                    "powered_on",
                    "powered_off",
                    "present",
                    "absent",
                    "restarted",
                    "reconfigured",
                ],
                default="present",
            ),
            vmware_guest_facts=dict(required=False, type="bool"),
            from_template=dict(required=False, type="bool"),
            template_src=dict(required=False, type="str"),
            snapshot_to_clone=dict(required=False, default=None, type="str"),
            guest=dict(required=True, type="str"),
            vm_disk=dict(required=False, type="dict", default={}),
            vm_nic=dict(required=False, type="dict", default={}),
            vm_hardware=dict(required=False, type="dict", default={}),
            vm_extra_config=dict(required=False, type="dict", default={}),
            vm_hw_version=dict(required=False, default=None, type="str"),
            resource_pool=dict(required=False, default=None, type="str"),
            cluster=dict(required=False, default=None, type="str"),
            force=dict(required=False, type="bool", default=False),
            esxi=dict(required=False, type="dict", default={}),
            validate_certs=dict(required=False, type="bool", default=True),
            power_on_after_clone=dict(required=False, type="bool", default=True),
        ),
        supports_check_mode=False,
        mutually_exclusive=[
            ["state", "vmware_guest_facts"],
            ["state", "from_template"],
        ],
        required_together=[
            ["state", "force"],
            ["state", "vm_disk", "vm_nic", "vm_hardware", "esxi"],
            ["from_template", "template_src"],
        ],
    )

    if not HAS_PYSPHERE:
        module.fail_json(msg="pysphere module required")

    vcenter_hostname = module.params["vcenter_hostname"]
    username = module.params["username"]
    password = module.params["password"]
    vmware_guest_facts = module.params["vmware_guest_facts"]
    state = module.params["state"]
    guest = module.params["guest"]
    force = module.params["force"]
    vm_disk = module.params["vm_disk"]
    vm_nic = module.params["vm_nic"]
    vm_hardware = module.params["vm_hardware"]
    vm_extra_config = module.params["vm_extra_config"]
    vm_hw_version = module.params["vm_hw_version"]
    esxi = module.params["esxi"]
    resource_pool = module.params["resource_pool"]
    cluster = module.params["cluster"]
    template_src = module.params["template_src"]
    from_template = module.params["from_template"]
    snapshot_to_clone = module.params["snapshot_to_clone"]
    power_on_after_clone = module.params["power_on_after_clone"]
    validate_certs = module.params["validate_certs"]

    # CONNECT TO THE SERVER
    viserver = VIServer()
    if (
        validate_certs
        and not hasattr(ssl, "SSLContext")
        and not vcenter_hostname.startswith("http://")
    ):
        module.fail_json(
            msg="pysphere does not support verifying certificates with python < 2.7.9.  Either update python or set "
            "validate_certs=False on the task"
        )

    try:
        viserver.connect(vcenter_hostname, username, password)
    except ssl.SSLError as sslerr:
        if "[SSL: CERTIFICATE_VERIFY_FAILED]" in sslerr.strerror:
            if not validate_certs:
                ssl._create_default_https_context
                ssl._create_default_https_context = ssl._create_unverified_context
                viserver.connect(vcenter_hostname, username, password)
            else:
                module.fail_json(
                    msg="Unable to validate the certificate of the vcenter host %s"
                    % vcenter_hostname
                )
        else:
            raise
    except VIApiException as err:
        module.fail_json(
            msg="Cannot connect to %s: %s" % (vcenter_hostname, to_native(err)),
            exception=traceback.format_exc(),
        )

    # Check if the VM exists before continuing
    try:
        vm = viserver.get_vm_by_name(guest)
    except Exception:
        pass

    if vm:
        # Run for facts only
        if vmware_guest_facts:
            try:
                module.exit_json(ansible_facts=gather_facts(vm))
            except Exception as e:
                module.fail_json(
                    msg="Fact gather failed with exception %s" % to_native(e),
                    exception=traceback.format_exc(),
                )
        # Power Changes
        elif state in ["powered_on", "powered_off", "restarted"]:
            state_result = power_state(vm, state, force)

            # Failure
            if isinstance(state_result, string_types):
                module.fail_json(msg=state_result)
            else:
                module.exit_json(changed=state_result)

        # Just check if there
        elif state == "present":
            module.exit_json(changed=False)

        # Fail on reconfig without params
        elif state == "reconfigured":
            reconfigure_vm(
                vsphere_client=viserver,
                vm=vm,
                module=module,
                esxi=esxi,
                resource_pool=resource_pool,
                cluster_name=cluster,
                guest=guest,
                vm_extra_config=vm_extra_config,
                vm_hardware=vm_hardware,
                vm_disk=vm_disk,
                vm_nic=vm_nic,
                state=state,
                force=force,
            )
        elif state == "absent":
            delete_vm(
                vsphere_client=viserver, module=module, guest=guest, vm=vm, force=force
            )

    # VM doesn't exist
    else:
        # Fail for fact gather task
        if vmware_guest_facts:
            module.fail_json(
                msg="No such VM %s. Fact gathering requires an existing vm" % guest
            )

        elif from_template:
            deploy_template(
                vsphere_client=viserver,
                esxi=esxi,
                resource_pool=resource_pool,
                guest=guest,
                template_src=template_src,
                module=module,
                cluster_name=cluster,
                snapshot_to_clone=snapshot_to_clone,
                power_on_after_clone=power_on_after_clone,
                vm_extra_config=vm_extra_config,
            )

        if state in ["restarted", "reconfigured"]:
            module.fail_json(
                msg="No such VM %s. States ["
                "restarted, reconfigured] required an existing VM" % guest
            )
        elif state == "absent":
            module.exit_json(changed=False, msg="vm %s not present" % guest)

        # check if user is trying to perform state operation on a vm which doesn't exists
        elif state in ["present", "powered_off", "powered_on"] and not all(
            (vm_extra_config, vm_hardware, vm_disk, vm_nic, esxi)
        ):
            module.exit_json(changed=False, msg="vm %s not present" % guest)

        # Create the VM
        elif state in ["present", "powered_off", "powered_on"]:
            # Check the guest_config
            config_check("vm_disk", vm_disk, proto_vm_disk, module)
            config_check("vm_nic", vm_nic, proto_vm_nic, module)
            config_check("vm_hardware", vm_hardware, proto_vm_hardware, module)
            config_check("esxi", esxi, proto_esxi, module)

            create_vm(
                vsphere_client=viserver,
                module=module,
                esxi=esxi,
                resource_pool=resource_pool,
                cluster_name=cluster,
                guest=guest,
                vm_extra_config=vm_extra_config,
                vm_hardware=vm_hardware,
                vm_disk=vm_disk,
                vm_nic=vm_nic,
                vm_hw_version=vm_hw_version,
                state=state,
            )

    viserver.disconnect()
    module.exit_json(changed=False, vcenter=vcenter_hostname)


# Traceback (TypeError)
AXSUNDHA-M-R10R:FreeBSD axsundha$ ansible-playbook -vvv CS_FreeBSD.yaml
[WARNING]: Optional dependency 'cryptography' raised an exception, falling back
to 'Crypto'

Using /Users/axsundha/ansible/Content_Security/FreeBSD/ansible.cfg as config file

PLAYBOOK: CS_FreeBSD.yaml ******************************************************
1 plays in CS_FreeBSD.yaml

PLAY [Playbook for Content Security servers] ***********************************

TASK [Start_VM : vsphere_guest] ************************************************
task path: /Users/axsundha/ansible/Content_Security/FreeBSD/roles/Start_VM/tasks/main.yml:3
<Guest hostname> ESTABLISH LOCAL CONNECTION FOR USER: axsundha
<Guest hostname> EXEC /bin/sh -c '( umask 77 &amp;&amp; mkdir -p "` echo $HOME/.ansible/tmp/ansible-tmp-1494941921.45-189921583388499 `" &amp;&amp; echo ansible-tmp-1494941921.45-189921583388499="` echo $HOME/.ansible/tmp/ansible-tmp-1494941921.45-189921583388499 `" ) &amp;&amp; sleep 0'
<Guest hostname> PUT /var/folders/br/2l8z6cfs03sfwszn020z2t5c0000gn/T/tmpRzc1us TO /Users/axsundha/.ansible/tmp/ansible-tmp-1494941921.45-189921583388499/vsphere_guest
<Guest hostname> EXEC /bin/sh -c 'LANG=en_US.UTF-8 LC_ALL=en_US.UTF-8 LC_MESSAGES=en_US.UTF-8 /usr/local/bin/python2.7 /Users/axsundha/.ansible/tmp/ansible-tmp-1494941921.45-189921583388499/vsphere_guest; rm -rf "/Users/axsundha/.ansible/tmp/ansible-tmp-1494941921.45-189921583388499/" > /dev/null 2>&amp;1 &amp;&amp; sleep 0'
An exception occurred during task execution. The full traceback is:
Traceback (most recent call last):
File "/var/folders/br/2l8z6cfs03sfwszn020z2t5c0000gn/T/ansible_2jRR_o/ansible_module_vsphere_guest.py", line 1879, in <module>
main()
File "/var/folders/br/2l8z6cfs03sfwszn020z2t5c0000gn/T/ansible_2jRR_o/ansible_module_vsphere_guest.py", line 1754, in main
viserver.connect(vcenter_hostname, username, password)
File "/Library/Python/2.7/site-packages/pysphere/vi_server.py", line 101, in connect
request)._returnval
File "/Library/Python/2.7/site-packages/pysphere/resources/VimService_services.py", line 2172, in RetrieveServiceContent
response = self.binding.Receive(RetrieveServiceContentResponseMsg.typecode)
File "/Library/Python/2.7/site-packages/pysphere/ZSI/client.py", line 540, in Receive
self.ReceiveSOAP(**kw)
File "/Library/Python/2.7/site-packages/pysphere/ZSI/client.py", line 425, in ReceiveSOAP
'Response is "%s", not "text/xml"' % self.local.reply_headers.type)
TypeError: Response is "text", not "text/xml"

fatal: [<Guest hostname>]: FAILED! => {"changed": false, "failed": true, "invocation": {"module_name": "vsphere_guest"}, "module_stderr": "Traceback (most recent call last):\n  File \"/var/folders/br/2l8z6cfs03sfwszn020z2t5c0000gn/T/ansible_2jRR_o/ansible_module_vsphere_guest.py\", line 1879, in <module>\n    main()\n  File \"/var/folders/br/2l8z6cfs03sfwszn020z2t5c0000gn/T/ansible_2jRR_o/ansible_module_vsphere_guest.py\", line 1754, in main\n    viserver.connect(vcenter_hostname, username, password)\n  File \"/Library/Python/2.7/site-packages/pysphere/vi_server.py\", line 101, in connect\n    request)._returnval\n  File \"/Library/Python/2.7/site-packages/pysphere/resources/VimService_services.py\", line 2172, in RetrieveServiceContent\n    response = self.binding.Receive(RetrieveServiceContentResponseMsg.typecode)\n  File \"/Library/Python/2.7/site-packages/pysphere/ZSI/client.py\", line 540, in Receive\n    self.ReceiveSOAP(**kw)\n  File \"/Library/Python/2.7/site-packages/pysphere/ZSI/client.py\", line 425, in ReceiveSOAP\n    'Response is \"%s\", not \"text/xml\"' % self.local.reply_headers.type)\nTypeError: Response is \"text\", not \"text/xml\"\n", "module_stdout": "", "msg": "MODULE FAILURE", "parsed": false}

NO MORE HOSTS LEFT *************************************************************
[WARNING]: Could not create retry file 'CS_FreeBSD.retry'.         [Errno 2] No
such file or directory: ''


PLAY RECAP *********************************************************************
<Guest hostname>          : ok=0    changed=0    unreachable=0    failed=1

# Fixed code
def main():
    vm = None

    proto_vm_hardware = {
        "memory_mb": int,
        "num_cpus": int,
        "scsi": string_types,
        "osid": string_types,
    }

    proto_vm_disk = {
        "disk1": {"datastore": string_types, "size_gb": int, "type": string_types}
    }

    proto_vm_nic = {
        "nic1": {
            "type": string_types,
            "network": string_types,
            "network_type": string_types,
        }
    }

    proto_esxi = {"datacenter": string_types, "hostname": string_types}

    module = AnsibleModule(
        argument_spec=dict(
            vcenter_hostname=dict(type="str", default=os.environ.get("VMWARE_HOST")),
            username=dict(type="str", default=os.environ.get("VMWARE_USER")),
            password=dict(
                type="str", no_log=True, default=os.environ.get("VMWARE_PASSWORD")
            ),
            state=dict(
                required=False,
                choices=[
                    "powered_on",
                    "powered_off",
                    "present",
                    "absent",
                    "restarted",
                    "reconfigured",
                ],
                default="present",
            ),
            vmware_guest_facts=dict(required=False, type="bool"),
            from_template=dict(required=False, type="bool"),
            template_src=dict(required=False, type="str"),
            snapshot_to_clone=dict(required=False, default=None, type="str"),
            guest=dict(required=True, type="str"),
            vm_disk=dict(required=False, type="dict", default={}),
            vm_nic=dict(required=False, type="dict", default={}),
            vm_hardware=dict(required=False, type="dict", default={}),
            vm_extra_config=dict(required=False, type="dict", default={}),
            vm_hw_version=dict(required=False, default=None, type="str"),
            resource_pool=dict(required=False, default=None, type="str"),
            cluster=dict(required=False, default=None, type="str"),
            force=dict(required=False, type="bool", default=False),
            esxi=dict(required=False, type="dict", default={}),
            validate_certs=dict(required=False, type="bool", default=True),
            power_on_after_clone=dict(required=False, type="bool", default=True),
        ),
        supports_check_mode=False,
        mutually_exclusive=[
            ["state", "vmware_guest_facts"],
            ["state", "from_template"],
        ],
        required_together=[
            ["state", "force"],
            ["state", "vm_disk", "vm_nic", "vm_hardware", "esxi"],
            ["from_template", "template_src"],
        ],
    )

    if not HAS_PYSPHERE:
        module.fail_json(msg="pysphere module required")

    vcenter_hostname = module.params["vcenter_hostname"]
    username = module.params["username"]
    password = module.params["password"]
    vmware_guest_facts = module.params["vmware_guest_facts"]
    state = module.params["state"]
    guest = module.params["guest"]
    force = module.params["force"]
    vm_disk = module.params["vm_disk"]
    vm_nic = module.params["vm_nic"]
    vm_hardware = module.params["vm_hardware"]
    vm_extra_config = module.params["vm_extra_config"]
    vm_hw_version = module.params["vm_hw_version"]
    esxi = module.params["esxi"]
    resource_pool = module.params["resource_pool"]
    cluster = module.params["cluster"]
    template_src = module.params["template_src"]
    from_template = module.params["from_template"]
    snapshot_to_clone = module.params["snapshot_to_clone"]
    power_on_after_clone = module.params["power_on_after_clone"]
    validate_certs = module.params["validate_certs"]

    # CONNECT TO THE SERVER
    viserver = VIServer()
    if (
        validate_certs
        and not hasattr(ssl, "SSLContext")
        and not vcenter_hostname.startswith("http://")
    ):
        module.fail_json(
            msg="pysphere does not support verifying certificates with python < 2.7.9.  Either update python or set "
            "validate_certs=False on the task"
        )

    if not validate_certs:
        ssl._create_default_https_context = ssl._create_unverified_context

    try:
        viserver.connect(vcenter_hostname, username, password)
    except ssl.SSLError as sslerr:
        module.fail_json(
            msg="Unable to validate the certificate of the vcenter hostname %s. Due to %s"
            % (vcenter_hostname, sslerr)
        )
    except socket.gaierror as err:
        module.fail_json(
            msg="Unable to resolve name for vcenter hostname: %s. Due to %s"
            % (vcenter_hostname, to_native(err))
        )
    except (TypeError, VIApiException) as err:
        module.fail_json(
            msg="Cannot connect to %s: %s" % (vcenter_hostname, to_native(err)),
            exception=traceback.format_exc(),
        )

    # Check if the VM exists before continuing
    try:
        vm = viserver.get_vm_by_name(guest)
    except Exception:
        pass

    if vm:
        # Run for facts only
        if vmware_guest_facts:
            try:
                module.exit_json(ansible_facts=gather_facts(vm))
            except Exception as e:
                module.fail_json(
                    msg="Fact gather failed with exception %s" % to_native(e),
                    exception=traceback.format_exc(),
                )
        # Power Changes
        elif state in ["powered_on", "powered_off", "restarted"]:
            state_result = power_state(vm, state, force)

            # Failure
            if isinstance(state_result, string_types):
                module.fail_json(msg=state_result)
            else:
                module.exit_json(changed=state_result)

        # Just check if there
        elif state == "present":
            module.exit_json(changed=False)

        # Fail on reconfig without params
        elif state == "reconfigured":
            reconfigure_vm(
                vsphere_client=viserver,
                vm=vm,
                module=module,
                esxi=esxi,
                resource_pool=resource_pool,
                cluster_name=cluster,
                guest=guest,
                vm_extra_config=vm_extra_config,
                vm_hardware=vm_hardware,
                vm_disk=vm_disk,
                vm_nic=vm_nic,
                state=state,
                force=force,
            )
        elif state == "absent":
            delete_vm(
                vsphere_client=viserver, module=module, guest=guest, vm=vm, force=force
            )

    # VM doesn't exist
    else:
        # Fail for fact gather task
        if vmware_guest_facts:
            module.fail_json(
                msg="No such VM %s. Fact gathering requires an existing vm" % guest
            )

        elif from_template:
            deploy_template(
                vsphere_client=viserver,
                esxi=esxi,
                resource_pool=resource_pool,
                guest=guest,
                template_src=template_src,
                module=module,
                cluster_name=cluster,
                snapshot_to_clone=snapshot_to_clone,
                power_on_after_clone=power_on_after_clone,
                vm_extra_config=vm_extra_config,
            )

        if state in ["restarted", "reconfigured"]:
            module.fail_json(
                msg="No such VM %s. States ["
                "restarted, reconfigured] required an existing VM" % guest
            )
        elif state == "absent":
            module.exit_json(changed=False, msg="vm %s not present" % guest)

        # check if user is trying to perform state operation on a vm which doesn't exists
        elif state in ["present", "powered_off", "powered_on"] and not all(
            (vm_extra_config, vm_hardware, vm_disk, vm_nic, esxi)
        ):
            module.exit_json(changed=False, msg="vm %s not present" % guest)

        # Create the VM
        elif state in ["present", "powered_off", "powered_on"]:
            # Check the guest_config
            config_check("vm_disk", vm_disk, proto_vm_disk, module)
            config_check("vm_nic", vm_nic, proto_vm_nic, module)
            config_check("vm_hardware", vm_hardware, proto_vm_hardware, module)
            config_check("esxi", esxi, proto_esxi, module)

            create_vm(
                vsphere_client=viserver,
                module=module,
                esxi=esxi,
                resource_pool=resource_pool,
                cluster_name=cluster,
                guest=guest,
                vm_extra_config=vm_extra_config,
                vm_hardware=vm_hardware,
                vm_disk=vm_disk,
                vm_nic=vm_nic,
                vm_hw_version=vm_hw_version,
                state=state,
            )

    viserver.disconnect()
    module.exit_json(changed=False, vcenter=vcenter_hostname)