Upload an ssh key for root to an ESXi host via http PUT.
    This function only works for ESXi, not vCenter.
    Only one ssh key can be uploaded for root.  Uploading a second key will
    replace any existing key.

    :param host: The location of the ESXi Host
    :param username: Username to connect as
    :param password: Password for the ESXi web endpoint
    :param ssh_key: Public SSH key, will be added to authorized_keys on ESXi
    :param ssh_key_file: File containing the SSH key.  Use 'ssh_key' or
                         ssh_key_file, but not both.
    :param protocol: defaults to https, can be http if ssl is disabled on ESXi
    :param port: defaults to 443 for https
    :param certificate_verify: If true require that the SSL connection present
                               a valid certificate
    :return: Dictionary with a 'status' key, True if upload is successful.
             If upload is unsuccessful, 'status' key will be False and
             an 'Error' key will have an informative message.

    CLI Example:

    .. code-block:: bash

        salt '*' vsphere.upload_ssh_key my.esxi.host root bad-password ssh_key_file='/etc/salt/my_keys/my_key.pub'

def upload_ssh_key(host, username, password, ssh_key=None, ssh_key_file=None,
                   protocol=None, port=None, certificate_verify=False):
    '''
    Upload an ssh key for root to an ESXi host via http PUT.
    This function only works for ESXi, not vCenter.
    Only one ssh key can be uploaded for root.  Uploading a second key will
    replace any existing key.

    :param host: The location of the ESXi Host
    :param username: Username to connect as
    :param password: Password for the ESXi web endpoint
    :param ssh_key: Public SSH key, will be added to authorized_keys on ESXi
    :param ssh_key_file: File containing the SSH key.  Use 'ssh_key' or
                         ssh_key_file, but not both.
    :param protocol: defaults to https, can be http if ssl is disabled on ESXi
    :param port: defaults to 443 for https
    :param certificate_verify: If true require that the SSL connection present
                               a valid certificate
    :return: Dictionary with a 'status' key, True if upload is successful.
             If upload is unsuccessful, 'status' key will be False and
             an 'Error' key will have an informative message.

    CLI Example:

    .. code-block:: bash

        salt '*' vsphere.upload_ssh_key my.esxi.host root bad-password ssh_key_file='/etc/salt/my_keys/my_key.pub'

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

    url = '{0}://{1}:{2}/host/ssh_root_authorized_keys'.format(protocol,
                                                               host,
                                                               port)
    ret = {}
    result = None
    try:
        if ssh_key:
            result = salt.utils.http.query(url,
                                           status=True,
                                           text=True,
                                           method='PUT',
                                           username=username,
                                           password=password,
                                           data=ssh_key,
                                           verify_ssl=certificate_verify)
        elif ssh_key_file:
            result = salt.utils.http.query(url,
                                           status=True,
                                           text=True,
                                           method='PUT',
                                           username=username,
                                           password=password,
                                           data_file=ssh_key_file,
                                           data_render=False,
                                           verify_ssl=certificate_verify)
        if result.get('status') == 200:
            ret['status'] = True
        else:
            ret['status'] = False
            ret['Error'] = result['error']
    except Exception as msg:
        ret['status'] = False
        ret['Error'] = msg

    return ret