Internal method to authenticate with a vCenter server or ESX/ESXi host
    and return the service instance object.

def _get_service_instance(host, username, password, protocol,
                          port, mechanism, principal, domain):
    '''
    Internal method to authenticate with a vCenter server or ESX/ESXi host
    and return the service instance object.
    '''
    log.trace('Retrieving new service instance')
    token = None
    if mechanism == 'userpass':
        if username is None:
            raise salt.exceptions.CommandExecutionError(
                'Login mechanism userpass was specified but the mandatory '
                'parameter \'username\' is missing')
        if password is None:
            raise salt.exceptions.CommandExecutionError(
                'Login mechanism userpass was specified but the mandatory '
                'parameter \'password\' is missing')
    elif mechanism == 'sspi':
        if principal is not None and domain is not None:
            try:
                token = get_gssapi_token(principal, host, domain)
            except Exception as exc:
                raise salt.exceptions.VMwareConnectionError(six.text_type(exc))
        else:
            err_msg = 'Login mechanism \'{0}\' was specified but the' \
                      ' mandatory parameters are missing'.format(mechanism)
            raise salt.exceptions.CommandExecutionError(err_msg)
    else:
        raise salt.exceptions.CommandExecutionError(
            'Unsupported mechanism: \'{0}\''.format(mechanism))
    try:
        log.trace('Connecting using the \'%s\' mechanism, with username \'%s\'',
                  mechanism, username)
        service_instance = SmartConnect(
            host=host,
            user=username,
            pwd=password,
            protocol=protocol,
            port=port,
            b64token=token,
            mechanism=mechanism)
    except TypeError as exc:
        if 'unexpected keyword argument' in exc.message:
            log.error('Initial connect to the VMware endpoint failed with %s', exc.message)
            log.error('This may mean that a version of PyVmomi EARLIER than 6.0.0.2016.6 is installed.')
            log.error('We recommend updating to that version or later.')
            raise
    except Exception as exc:  # pylint: disable=broad-except
        # pyVmomi's SmartConnect() actually raises Exception in some cases.
        default_msg = 'Could not connect to host \'{0}\'. ' \
                      'Please check the debug log for more information.'.format(host)

        try:
            if (isinstance(exc, vim.fault.HostConnectFault) and
                '[SSL: CERTIFICATE_VERIFY_FAILED]' in exc.msg) or \
               '[SSL: CERTIFICATE_VERIFY_FAILED]' in six.text_type(exc):
                service_instance = SmartConnect(
                    host=host,
                    user=username,
                    pwd=password,
                    protocol=protocol,
                    port=port,
                    sslContext=getattr(ssl, '_create_unverified_context', getattr(ssl, '_create_stdlib_context'))(),
                    b64token=token,
                    mechanism=mechanism)
            else:
                log.exception(exc)
                err_msg = exc.msg if hasattr(exc, 'msg') else default_msg
                raise salt.exceptions.VMwareConnectionError(err_msg)
        except Exception as exc:  # pylint: disable=broad-except
            # pyVmomi's SmartConnect() actually raises Exception in some cases.
            if 'certificate verify failed' in six.text_type(exc):
                context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
                context.verify_mode = ssl.CERT_NONE
                try:
                    service_instance = SmartConnect(
                        host=host,
                        user=username,
                        pwd=password,
                        protocol=protocol,
                        port=port,
                        sslContext=context,
                        b64token=token,
                        mechanism=mechanism
                    )
                except Exception as exc:
                    log.exception(exc)
                    err_msg = exc.msg if hasattr(exc, 'msg') else six.text_type(exc)
                    raise salt.exceptions.VMwareConnectionError(
                        'Could not connect to host \'{0}\': '
                        '{1}'.format(host, err_msg))
            else:
                err_msg = exc.msg if hasattr(exc, 'msg') else default_msg
                log.trace(exc)
                raise salt.exceptions.VMwareConnectionError(err_msg)
    atexit.register(Disconnect, service_instance)
    return service_instance