# Buggy code
def get_service_instance(
    host,
    username=None,
    password=None,
    protocol=None,
    port=None,
    mechanism="userpass",
    principal=None,
    domain=None,
):
    """
    Authenticate with a vCenter server or ESX/ESXi host and return the service instance object.

    host
        The location of the vCenter server or ESX/ESXi host.

    username
        The username used to login to the vCenter server or ESX/ESXi host.
        Required if mechanism is ``userpass``

    password
        The password used to login to the vCenter server or ESX/ESXi host.
        Required if mechanism is ``userpass``

    protocol
        Optionally set to alternate protocol if the vCenter server or ESX/ESXi host is not
        using the default protocol. Default protocol is ``https``.

    port
        Optionally set to alternate port if the vCenter server or ESX/ESXi host is not
        using the default port. Default port is ``443``.

    mechanism
        pyVmomi connection mechanism. Can either be ``userpass`` or ``sspi``.
        Default mechanism is ``userpass``.

    principal
        Kerberos service principal. Required if mechanism is ``sspi``

    domain
        Kerberos user domain. Required if mechanism is ``sspi``
    """

    if protocol is None:
        protocol = "https"
    if port is None:
        port = 443

    service_instance = GetSi()
    if service_instance:
        stub = GetStub()
        if salt.utils.platform.is_proxy() or (
            hasattr(stub, "host") and stub.host != ":".join([host, str(port)])
        ):
            # Proxies will fork and mess up the cached service instance.
            # If this is a proxy or we are connecting to a different host
            # invalidate the service instance to avoid a potential memory leak
            # and reconnect
            Disconnect(service_instance)
            service_instance = None
        else:
            return service_instance

    if not service_instance:
        service_instance = _get_service_instance(
            host, username, password, protocol, port, mechanism, principal, domain
        )

    # Test if data can actually be retrieved or connection has gone stale
    log.trace("Checking connection is still authenticated")
    try:
        service_instance.CurrentTime()
    except vim.fault.NotAuthenticated:
        log.trace("Session no longer authenticating. Reconnecting")
        Disconnect(service_instance)
        service_instance = _get_service_instance(
            host, username, password, protocol, port, mechanism, principal, domain
        )
    except vim.fault.NoPermission as exc:
        log.exception(exc)
        raise salt.exceptions.VMwareApiError(
            "Not enough permissions. Required privilege: {}".format(exc.privilegeId)
        )
    except vim.fault.VimFault as exc:
        log.exception(exc)
        raise salt.exceptions.VMwareApiError(exc.msg)
    except vmodl.RuntimeFault as exc:
        log.exception(exc)
        raise salt.exceptions.VMwareRuntimeError(exc.msg)

    return service_instance


# Traceback (salt.exceptions.VMwareApiError)
Exception occurred in runner vmware_auth_test.minimal: Traceback (most recent call last):
File "/usr/lib/python3.6/site-packages/salt/utils/vmware.py", line 904, in get_content
container_ref, [obj_type], True
File "/usr/local/lib/python3.6/site-packages/pyVmomi/VmomiSupport.py", line 706, in <lambda>
self.f(*(self.args + (obj,) + args), **kwargs)
File "/usr/local/lib/python3.6/site-packages/pyVmomi/VmomiSupport.py", line 512, in _InvokeMethod
return self._stub.InvokeMethod(self, info, args)
File "/usr/local/lib/python3.6/site-packages/pyVmomi/SoapAdapter.py", line 1397, in InvokeMethod
raise obj # pylint: disable-msg=E0702
pyVmomi.VmomiSupport.vim.fault.NotAuthenticated: (vim.fault.NotAuthenticated) {
dynamicType = <unset>,
dynamicProperty = (vmodl.DynamicProperty) [],
msg = 'The session is not authenticated.',
faultCause = <unset>,
faultMessage = (vmodl.LocalizableMessage) [],
object = 'vim.Folder:group-d1',
privilegeId = 'System.View'
}

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "/usr/lib/python3.6/site-packages/salt/client/mixins.py", line 397, in low
data["return"] = func(*args, **kwargs)
File "/var/cache/salt/master/extmods/runners/vmware_auth_test.py", line 5, in minimal
result = cloud_client.action(fun="list_nodes", provider="my-vsphere-provider")
File "/usr/lib/python3.6/site-packages/salt/cloud/__init__.py", line 503, in action
return mapper.do_function(provider, fun, kwargs)
File "/usr/lib/python3.6/site-packages/salt/cloud/__init__.py", line 1567, in do_function
return {alias: {driver: self.clouds[fun](call="function")}}
File "/usr/lib/python3.6/site-packages/salt/cloud/clouds/vmware.py", line 1997, in list_nodes
_get_si(), vim.VirtualMachine, vm_properties
File "/usr/lib/python3.6/site-packages/salt/utils/vmware.py", line 1069, in get_mors_with_properties
content = get_content(*content_args, **content_kwargs)
File "/usr/lib/python3.6/site-packages/salt/utils/vmware.py", line 910, in get_content
"{}".format(exc.privilegeId)
salt.exceptions.VMwareApiError: Not enough permissions. Required privilege: System.View

# Fixed code
def get_service_instance(
    host,
    username=None,
    password=None,
    protocol=None,
    port=None,
    mechanism="userpass",
    principal=None,
    domain=None,
):
    """
    Authenticate with a vCenter server or ESX/ESXi host and return the service instance object.

    host
        The location of the vCenter server or ESX/ESXi host.

    username
        The username used to login to the vCenter server or ESX/ESXi host.
        Required if mechanism is ``userpass``

    password
        The password used to login to the vCenter server or ESX/ESXi host.
        Required if mechanism is ``userpass``

    protocol
        Optionally set to alternate protocol if the vCenter server or ESX/ESXi host is not
        using the default protocol. Default protocol is ``https``.

    port
        Optionally set to alternate port if the vCenter server or ESX/ESXi host is not
        using the default port. Default port is ``443``.

    mechanism
        pyVmomi connection mechanism. Can either be ``userpass`` or ``sspi``.
        Default mechanism is ``userpass``.

    principal
        Kerberos service principal. Required if mechanism is ``sspi``

    domain
        Kerberos user domain. Required if mechanism is ``sspi``
    """

    if protocol is None:
        protocol = "https"
    if port is None:
        port = 443

    service_instance = GetSi()
    if service_instance:
        stub = GetStub()
        if salt.utils.platform.is_proxy() or (
            hasattr(stub, "host") and stub.host != ":".join([host, str(port)])
        ):
            # Proxies will fork and mess up the cached service instance.
            # If this is a proxy or we are connecting to a different host
            # invalidate the service instance to avoid a potential memory leak
            # and reconnect
            Disconnect(service_instance)
            service_instance = None

    if not service_instance:
        service_instance = _get_service_instance(
            host, username, password, protocol, port, mechanism, principal, domain
        )

    # Test if data can actually be retrieved or connection has gone stale
    log.trace("Checking connection is still authenticated")
    try:
        service_instance.CurrentTime()
    except vim.fault.NotAuthenticated:
        log.trace("Session no longer authenticating. Reconnecting")
        Disconnect(service_instance)
        service_instance = _get_service_instance(
            host, username, password, protocol, port, mechanism, principal, domain
        )
    except vim.fault.NoPermission as exc:
        log.exception(exc)
        raise salt.exceptions.VMwareApiError(
            "Not enough permissions. Required privilege: {}".format(exc.privilegeId)
        )
    except vim.fault.VimFault as exc:
        log.exception(exc)
        raise salt.exceptions.VMwareApiError(exc.msg)
    except vmodl.RuntimeFault as exc:
        log.exception(exc)
        raise salt.exceptions.VMwareRuntimeError(exc.msg)

    return service_instance