"""
Module to provide Citrix Netscaler compatibility to Salt (compatible with netscaler 9.2+)

.. versionadded:: 2015.2.0

:depends:

- nsnitro Python module

.. note::
    You can install nsnitro using:

    .. code-block:: bash

        pip install nsnitro

:configuration: This module accepts connection configuration details either as
    parameters, or as configuration settings in /etc/salt/minion on the relevant
    minions

    .. code-block:: yaml

        netscaler.host: 1.2.3.4
        netscaler.user: user
        netscaler.pass: password

    This data can also be passed into pillar. Options passed into opts will
    overwrite options passed into pillar.

CLI Examples:

    Calls relying on configuration passed using /etc/salt/minion, grains, or pillars:

    .. code-block:: bash

        salt-call netscaler.server_exists server_name

    Calls passing configuration as opts

    .. code-block:: bash

        salt-call netscaler.server_exists server_name netscaler_host=1.2.3.4 netscaler_user=username netscaler_pass=password
        salt-call netscaler.server_exists server_name netscaler_host=1.2.3.5 netscaler_user=username2 netscaler_pass=password2
        salt-call netscaler.server_enable server_name2 netscaler_host=1.2.3.5
        salt-call netscaler.server_up server_name3 netscaler_host=1.2.3.6 netscaler_useSSL=False

"""

import logging

import salt.utils.platform

try:
    from nsnitro.nsexceptions import NSNitroError
    from nsnitro.nsnitro import NSNitro
    from nsnitro.nsresources.nslbvserver import NSLBVServer
    from nsnitro.nsresources.nslbvserverservicegroupbinding import (
        NSLBVServerServiceGroupBinding,
    )
    from nsnitro.nsresources.nsserver import NSServer
    from nsnitro.nsresources.nsservice import NSService
    from nsnitro.nsresources.nsservicegroup import NSServiceGroup
    from nsnitro.nsresources.nsservicegroupserverbinding import (
        NSServiceGroupServerBinding,
    )
    from nsnitro.nsresources.nssslvserversslcertkeybinding import (
        NSSSLVServerSSLCertKeyBinding,
    )

    HAS_NSNITRO = True
except ImportError:
    HAS_NSNITRO = False

log = logging.getLogger(__name__)


def __virtual__():
    """
    Only load this module if the nsnitro library is installed
    """
    if salt.utils.platform.is_windows():
        return (
            False,
            "The netscaler execution module failed to load: not available on Windows.",
        )
    if HAS_NSNITRO:
        return "netscaler"
    return (
        False,
        "The netscaler execution module failed to load: the nsnitro python "
        "library is not available.",
    )


def _connect(**kwargs):
    """
    Initialise netscaler connection
    """
    connargs = dict()

    # Shamelessy ripped from the mysql module
    def __connarg(name, key=None, default=None):
        """
        Add key to connargs, only if name exists in our kwargs or as
        netscaler.<name> in __opts__ or __pillar__ Evaluate in said order - kwargs,
        opts then pillar. To avoid collision with other functions, kwargs-based
        connection arguments are prefixed with 'netscaler_' (i.e.
        'netscaler_host', 'netscaler_user', etc.).
        """
        if key is None:
            key = name
        if name in kwargs:
            connargs[key] = kwargs[name]
        else:
            prefix = "netscaler_"
            if name.startswith(prefix):
                try:
                    name = name[len(prefix) :]
                except IndexError:
                    return
            val = __salt__["config.option"](f"netscaler.{name}", None)
            if val is not None:
                connargs[key] = val
            elif default is not None:
                connargs[key] = default

    __connarg("netscaler_host", "host")
    __connarg("netscaler_user", "user")
    __connarg("netscaler_pass", "pass")
    __connarg("netscaler_useSSL", "useSSL", True)

    nitro = NSNitro(
        connargs["host"], connargs["user"], connargs["pass"], connargs["useSSL"]
    )
    try:
        nitro.login()
    except NSNitroError as error:
        log.debug("netscaler module error - NSNitro.login() failed: %s", error)
        return None
    return nitro


def _disconnect(nitro):
    try:
        nitro.logout()
    except NSNitroError as error:
        log.debug("netscaler module error - NSNitro.logout() failed: %s", error)
        return None
    return nitro


def _servicegroup_get(sg_name, **connection_args):
    """
    Return a service group ressource or None
    """
    nitro = _connect(**connection_args)
    if nitro is None:
        return None
    sg = NSServiceGroup()
    sg.set_servicegroupname(sg_name)
    try:
        sg = NSServiceGroup.get(nitro, sg)
    except NSNitroError as error:
        log.debug("netscaler module error - NSServiceGroup.get() failed: %s", error)
        sg = None
    _disconnect(nitro)
    return sg


def _servicegroup_get_servers(sg_name, **connection_args):
    """
    Returns a list of members of a servicegroup or None
    """
    nitro = _connect(**connection_args)
    if nitro is None:
        return None
    sg = NSServiceGroup()
    sg.set_servicegroupname(sg_name)
    try:
        sg = NSServiceGroup.get_servers(nitro, sg)
    except NSNitroError as error:
        log.debug(
            "netscaler module error - NSServiceGroup.get_servers failed(): %s", error
        )
        sg = None
    _disconnect(nitro)
    return sg


def _servicegroup_get_server(sg_name, s_name, s_port=None, **connection_args):
    """
    Returns a member of a service group or None
    """
    ret = None
    servers = _servicegroup_get_servers(sg_name, **connection_args)
    if servers is None:
        return None
    for server in servers:
        if server.get_servername() == s_name:
            if s_port is not None and s_port != server.get_port():
                ret = None
            ret = server
    return ret


def servicegroup_exists(sg_name, sg_type=None, **connection_args):
    """
    Checks if a service group exists

    CLI Example:

    .. code-block:: bash

        salt '*' netscaler.servicegroup_exists 'serviceGroupName'
    """
    sg = _servicegroup_get(sg_name, **connection_args)
    if sg is None:
        return False
    if sg_type is not None and sg_type.upper() != sg.get_servicetype():
        return False
    return True


def servicegroup_add(sg_name, sg_type="HTTP", **connection_args):
    """
    Add a new service group
    If no service type is specified, HTTP will be used.
    Most common service types: HTTP, SSL, and SSL_BRIDGE

    CLI Example:

    .. code-block:: bash

        salt '*' netscaler.servicegroup_add 'serviceGroupName'
        salt '*' netscaler.servicegroup_add 'serviceGroupName' 'serviceGroupType'
    """
    ret = True
    if servicegroup_exists(sg_name):
        return False
    nitro = _connect(**connection_args)
    if nitro is None:
        return False
    sg = NSServiceGroup()
    sg.set_servicegroupname(sg_name)
    sg.set_servicetype(sg_type.upper())
    try:
        NSServiceGroup.add(nitro, sg)
    except NSNitroError as error:
        log.debug("netscaler module error - NSServiceGroup.add() failed: %s", error)
        ret = False
    _disconnect(nitro)
    return ret


def servicegroup_delete(sg_name, **connection_args):
    """
    Delete a new service group

    CLI Example:

    .. code-block:: bash

        salt '*' netscaler.servicegroup_delete 'serviceGroupName'
    """
    ret = True
    sg = _servicegroup_get(sg_name, **connection_args)
    if sg is None:
        return False
    nitro = _connect(**connection_args)
    if nitro is None:
        return False
    try:
        NSServiceGroup.delete(nitro, sg)
    except NSNitroError as error:
        log.debug("netscaler module error - NSServiceGroup.delete() failed: %s", error)
        ret = False
    _disconnect(nitro)
    return ret


def servicegroup_server_exists(sg_name, s_name, s_port=None, **connection_args):
    """
    Check if a server:port combination is a member of a servicegroup

    CLI Example:

    .. code-block:: bash

        salt '*' netscaler.servicegroup_server_exists 'serviceGroupName' 'serverName' 'serverPort'
    """
    return (
        _servicegroup_get_server(sg_name, s_name, s_port, **connection_args) is not None
    )


def servicegroup_server_up(sg_name, s_name, s_port, **connection_args):
    """
    Check if a server:port combination is in state UP in a servicegroup

    CLI Example:

    .. code-block:: bash

        salt '*' netscaler.servicegroup_server_up 'serviceGroupName' 'serverName' 'serverPort'
    """
    server = _servicegroup_get_server(sg_name, s_name, s_port, **connection_args)
    return server is not None and server.get_svrstate() == "UP"


def servicegroup_server_enable(sg_name, s_name, s_port, **connection_args):
    """
    Enable a server:port member of a servicegroup

    CLI Example:

    .. code-block:: bash

        salt '*' netscaler.servicegroup_server_enable 'serviceGroupName' 'serverName' 'serverPort'
    """
    ret = True
    server = _servicegroup_get_server(sg_name, s_name, s_port, **connection_args)
    if server is None:
        return False
    nitro = _connect(**connection_args)
    if nitro is None:
        return False
    try:
        NSServiceGroup.enable_server(nitro, server)
    except NSNitroError as error:
        log.debug(
            "netscaler module error - NSServiceGroup.enable_server() failed: %s", error
        )
        ret = False
    _disconnect(nitro)
    return ret


def servicegroup_server_disable(sg_name, s_name, s_port, **connection_args):
    """
    Disable a server:port member of a servicegroup

    CLI Example:

    .. code-block:: bash

        salt '*' netscaler.servicegroup_server_disable 'serviceGroupName' 'serverName' 'serverPort'
    """
    ret = True
    server = _servicegroup_get_server(sg_name, s_name, s_port, **connection_args)
    if server is None:
        return False
    nitro = _connect(**connection_args)
    if nitro is None:
        return False
    try:
        NSServiceGroup.disable_server(nitro, server)
    except NSNitroError as error:
        log.debug(
            "netscaler module error - NSServiceGroup.disable_server() failed: %s", error
        )
        ret = False
    _disconnect(nitro)
    return ret


def servicegroup_server_add(sg_name, s_name, s_port, **connection_args):
    """
    Add a server:port member to a servicegroup

    CLI Example:

    .. code-block:: bash

        salt '*' netscaler.servicegroup_server_add 'serviceGroupName' 'serverName' 'serverPort'
    """
    # Nitro will throw an error if the server is already present
    ret = True
    server = _servicegroup_get_server(sg_name, s_name, s_port, **connection_args)
    if server is not None:
        return False
    nitro = _connect(**connection_args)
    if nitro is None:
        return False
    sgsb = NSServiceGroupServerBinding()
    sgsb.set_servicegroupname(sg_name)
    sgsb.set_servername(s_name)
    sgsb.set_port(s_port)
    try:
        NSServiceGroupServerBinding.add(nitro, sgsb)
    except NSNitroError as error:
        log.debug(
            "netscaler module error - NSServiceGroupServerBinding() failed: %s", error
        )
        ret = False
    _disconnect(nitro)
    return ret


def servicegroup_server_delete(sg_name, s_name, s_port, **connection_args):
    """
    Remove a server:port member from a servicegroup

    CLI Example:

    .. code-block:: bash

        salt '*' netscaler.servicegroup_server_delete 'serviceGroupName' 'serverName' 'serverPort'
    """
    # Nitro will throw an error if the server is already not present
    ret = True
    server = _servicegroup_get_server(sg_name, s_name, s_port, **connection_args)
    if server is None:
        return False
    nitro = _connect(**connection_args)
    if nitro is None:
        return False
    sgsb = NSServiceGroupServerBinding()
    sgsb.set_servicegroupname(sg_name)
    sgsb.set_servername(s_name)
    sgsb.set_port(s_port)
    try:
        NSServiceGroupServerBinding.delete(nitro, sgsb)
    except NSNitroError as error:
        log.debug(
            "netscaler module error - NSServiceGroupServerBinding() failed: %s", error
        )
        ret = False
    _disconnect(nitro)
    return ret


def _service_get(s_name, **connection_args):
    """
    Returns a service ressource or None
    """
    nitro = _connect(**connection_args)
    if nitro is None:
        return None
    service = NSService()
    service.set_name(s_name)
    try:
        service = NSService.get(nitro, service)
    except NSNitroError as error:
        log.debug("netscaler module error - NSService.get() failed: %s", error)
        service = None
    _disconnect(nitro)
    return service


def service_exists(s_name, **connection_args):
    """
    Checks if a service exists

    CLI Example:

    .. code-block:: bash

        salt '*' netscaler.service_exists 'serviceName'
    """
    return _service_get(s_name, **connection_args) is not None


def service_up(s_name, **connection_args):
    """
    Checks if a service is UP

    CLI Example:

    .. code-block:: bash

        salt '*' netscaler.service_up 'serviceName'
    """
    service = _service_get(s_name, **connection_args)
    return service is not None and service.get_svrstate() == "UP"


def service_enable(s_name, **connection_args):
    """
    Enable a service

    CLI Example:

    .. code-block:: bash

        salt '*' netscaler.service_enable 'serviceName'
    """
    ret = True
    service = _service_get(s_name, **connection_args)
    if service is None:
        return False
    nitro = _connect(**connection_args)
    if nitro is None:
        return False
    try:
        NSService.enable(nitro, service)
    except NSNitroError as error:
        log.debug("netscaler module error - NSService.enable() failed: %s", error)
        ret = False
    _disconnect(nitro)
    return ret


def service_disable(s_name, s_delay=None, **connection_args):
    """
    Disable a service

    CLI Example:

    .. code-block:: bash

        salt '*' netscaler.service_disable 'serviceName'
        salt '*' netscaler.service_disable 'serviceName' 'delayInSeconds'
    """
    ret = True
    service = _service_get(s_name, **connection_args)
    if service is None:
        return False
    if s_delay is not None:
        service.set_delay(s_delay)
    nitro = _connect(**connection_args)
    if nitro is None:
        return False
    try:
        NSService.disable(nitro, service)
    except NSNitroError as error:
        log.debug("netscaler module error - NSService.enable() failed: %s", error)
        ret = False
    _disconnect(nitro)
    return ret


def _server_get(s_name, **connection_args):
    nitro = _connect(**connection_args)
    if nitro is None:
        return None
    server = NSServer()
    server.set_name(s_name)
    try:
        server = NSServer.get(nitro, server)
    except NSNitroError as error:
        log.debug("netscaler module error - NSServer.get() failed: %s", error)
        server = None
    _disconnect(nitro)
    return server


def server_exists(s_name, ip=None, s_state=None, **connection_args):
    """
    Checks if a server exists

    CLI Example:

    .. code-block:: bash

        salt '*' netscaler.server_exists 'serverName'
    """
    server = _server_get(s_name, **connection_args)
    if server is None:
        return False
    if ip is not None and ip != server.get_ipaddress():
        return False
    if s_state is not None and s_state.upper() != server.get_state():
        return False
    return True


def server_add(s_name, s_ip, s_state=None, **connection_args):
    """
    Add a server
    Note: The default server state is ENABLED

    CLI Example:

    .. code-block:: bash

        salt '*' netscaler.server_add 'serverName' 'serverIpAddress'
        salt '*' netscaler.server_add 'serverName' 'serverIpAddress' 'serverState'
    """
    ret = True
    if server_exists(s_name, **connection_args):
        return False
    nitro = _connect(**connection_args)
    if nitro is None:
        return False
    server = NSServer()
    server.set_name(s_name)
    server.set_ipaddress(s_ip)
    if s_state is not None:
        server.set_state(s_state)
    try:
        NSServer.add(nitro, server)
    except NSNitroError as error:
        log.debug("netscaler module error - NSServer.add() failed: %s", error)
        ret = False
    _disconnect(nitro)
    return ret


def server_delete(s_name, **connection_args):
    """
    Delete a server

    CLI Example:

    .. code-block:: bash

        salt '*' netscaler.server_delete 'serverName'
    """
    ret = True
    server = _server_get(s_name, **connection_args)
    if server is None:
        return False
    nitro = _connect(**connection_args)
    if nitro is None:
        return False
    try:
        NSServer.delete(nitro, server)
    except NSNitroError as error:
        log.debug("netscaler module error - NSServer.delete() failed: %s", error)
        ret = False
    _disconnect(nitro)
    return ret


def server_update(s_name, s_ip, **connection_args):
    """
    Update a server's attributes

    CLI Example:

    .. code-block:: bash

      salt '*' netscaler.server_update 'serverName' 'serverIP'
    """
    altered = False
    cur_server = _server_get(s_name, **connection_args)
    if cur_server is None:
        return False
    alt_server = NSServer()
    alt_server.set_name(s_name)
    if cur_server.get_ipaddress() != s_ip:
        alt_server.set_ipaddress(s_ip)
        altered = True
    # Nothing to update, the server is already idem
    if altered is False:
        return False
    # Perform the update
    nitro = _connect(**connection_args)
    if nitro is None:
        return False
    ret = True
    try:
        NSServer.update(nitro, alt_server)
    except NSNitroError as error:
        log.debug("netscaler module error - NSServer.update() failed: %s", error)
        ret = False
    _disconnect(nitro)
    return ret


def server_enabled(s_name, **connection_args):
    """
    Check if a server is enabled globally

    CLI Example:

    .. code-block:: bash

        salt '*' netscaler.server_enabled 'serverName'
    """
    server = _server_get(s_name, **connection_args)
    return server is not None and server.get_state() == "ENABLED"


def server_enable(s_name, **connection_args):
    """
    Enables a server globally

    CLI Example:

    .. code-block:: bash

        salt '*' netscaler.server_enable 'serverName'
    """
    ret = True
    server = _server_get(s_name, **connection_args)
    if server is None:
        return False
    if server.get_state() == "ENABLED":
        return True
    nitro = _connect(**connection_args)
    if nitro is None:
        return False
    try:
        NSServer.enable(nitro, server)
    except NSNitroError as error:
        log.debug("netscaler module error - NSServer.enable() failed: %s", error)
        ret = False
    _disconnect(nitro)
    return ret


def server_disable(s_name, **connection_args):
    """
    Disable a server globally

    CLI Example:

    .. code-block:: bash

        salt '*' netscaler.server_disable 'serverName'
    """
    ret = True
    server = _server_get(s_name, **connection_args)
    if server is None:
        return False
    if server.get_state() == "DISABLED":
        return True
    nitro = _connect(**connection_args)
    if nitro is None:
        return False
    try:
        NSServer.disable(nitro, server)
    except NSNitroError as error:
        log.debug("netscaler module error - NSServer.disable() failed: %s", error)
        ret = False
    _disconnect(nitro)
    return ret


def _vserver_get(v_name, **connection_args):
    nitro = _connect(**connection_args)
    vserver = NSLBVServer()
    vserver.set_name(v_name)
    if nitro is None:
        return None
    try:
        vserver = NSLBVServer.get(nitro, vserver)
    except NSNitroError as error:
        log.debug("netscaler module error - NSLBVServer.get() failed: %s", error)
        vserver = None
    _disconnect(nitro)
    return vserver


def vserver_exists(v_name, v_ip=None, v_port=None, v_type=None, **connection_args):
    """
    Checks if a vserver exists

    CLI Example:

    .. code-block:: bash

        salt '*' netscaler.vserver_exists 'vserverName'
    """
    vserver = _vserver_get(v_name, **connection_args)
    if vserver is None:
        return False
    if v_ip is not None and vserver.get_ipv46() != v_ip:
        return False
    if v_port is not None and vserver.get_port() != v_port:
        return False
    if v_type is not None and vserver.get_servicetype().upper() != v_type.upper():
        return False
    return True


def vserver_add(v_name, v_ip, v_port, v_type, **connection_args):
    """
    Add a new lb vserver

    CLI Example:

    .. code-block:: bash

        salt '*' netscaler.vserver_add 'vserverName' 'vserverIP' 'vserverPort' 'vserverType'
        salt '*' netscaler.vserver_add 'alex.patate.chaude.443' '1.2.3.4' '443' 'SSL'
    """
    ret = True
    if vserver_exists(v_name, **connection_args):
        return False
    nitro = _connect(**connection_args)
    if nitro is None:
        return False
    vserver = NSLBVServer()
    vserver.set_name(v_name)
    vserver.set_ipv46(v_ip)
    vserver.set_port(v_port)
    vserver.set_servicetype(v_type.upper())
    try:
        NSLBVServer.add(nitro, vserver)
    except NSNitroError as error:
        log.debug("netscaler module error - NSLBVServer.add() failed: %s", error)
        ret = False
    _disconnect(nitro)
    return ret


def vserver_delete(v_name, **connection_args):
    """
    Delete a lb vserver

    CLI Example:

    .. code-block:: bash

        salt '*' netscaler.vserver_delete 'vserverName'
    """
    ret = True
    vserver = _vserver_get(v_name, **connection_args)
    if vserver is None:
        return False
    nitro = _connect(**connection_args)
    if nitro is None:
        return False
    try:
        NSLBVServer.delete(nitro, vserver)
    except NSNitroError as error:
        log.debug("netscaler module error - NSVServer.delete() failed: %s", error)
        ret = False
    _disconnect(nitro)
    return ret


def _vserver_servicegroup_get(v_name, sg_name, **connection_args):
    ret = None
    nitro = _connect(**connection_args)
    if nitro is None:
        return None
    vsg = NSLBVServerServiceGroupBinding()
    vsg.set_name(v_name)
    try:
        vsgs = NSLBVServerServiceGroupBinding.get(nitro, vsg)
    except NSNitroError as error:
        log.debug(
            "netscaler module error - NSLBVServerServiceGroupBinding.get() failed: %s",
            error,
        )
        return None
    for vsg in vsgs:
        if vsg.get_servicegroupname() == sg_name:
            ret = vsg
    _disconnect(nitro)
    return ret


def vserver_servicegroup_exists(v_name, sg_name, **connection_args):
    """
    Checks if a servicegroup is tied to a vserver

    CLI Example:

    .. code-block:: bash

        salt '*' netscaler.vserver_servicegroup_exists 'vserverName' 'serviceGroupName'
    """
    return _vserver_servicegroup_get(v_name, sg_name, **connection_args) is not None


def vserver_servicegroup_add(v_name, sg_name, **connection_args):
    """
    Bind a servicegroup to a vserver

    CLI Example:

    .. code-block:: bash

        salt '*' netscaler.vserver_servicegroup_add 'vserverName' 'serviceGroupName'
    """
    ret = True
    if vserver_servicegroup_exists(v_name, sg_name, **connection_args):
        return False
    nitro = _connect(**connection_args)
    if nitro is None:
        return False
    vsg = NSLBVServerServiceGroupBinding()
    vsg.set_name(v_name)
    vsg.set_servicegroupname(sg_name)
    try:
        NSLBVServerServiceGroupBinding.add(nitro, vsg)
    except NSNitroError as error:
        log.debug(
            "netscaler module error - NSLBVServerServiceGroupBinding.add() failed: %s",
            error,
        )
        ret = False
    _disconnect(nitro)
    return ret


def vserver_servicegroup_delete(v_name, sg_name, **connection_args):
    """
    Unbind a servicegroup from a vserver

    CLI Example:

    .. code-block:: bash

        salt '*' netscaler.vserver_servicegroup_delete 'vserverName' 'serviceGroupName'
    """
    ret = True
    if not vserver_servicegroup_exists(v_name, sg_name, **connection_args):
        return False
    nitro = _connect(**connection_args)
    if nitro is None:
        return False
    vsg = NSLBVServerServiceGroupBinding()
    vsg.set_name(v_name)
    vsg.set_servicegroupname(sg_name)
    try:
        NSLBVServerServiceGroupBinding.delete(nitro, vsg)
    except NSNitroError as error:
        log.debug(
            "netscaler module error - NSLBVServerServiceGroupBinding.delete()"
            " failed: %s",
            error,
        )
        ret = False
    _disconnect(nitro)
    return ret


def _vserver_sslcert_get(v_name, sc_name, **connection_args):
    ret = None
    nitro = _connect(**connection_args)
    if nitro is None:
        return None
    sslcert = NSSSLVServerSSLCertKeyBinding()
    sslcert.set_vservername(v_name)
    try:
        sslcerts = NSSSLVServerSSLCertKeyBinding.get(nitro, sslcert)
    except NSNitroError as error:
        log.debug(
            "netscaler module error - NSSSLVServerSSLCertKeyBinding.get() failed: %s",
            error,
        )
        return None
    for sslcert in sslcerts:
        if sslcert.get_certkeyname() == sc_name:
            ret = sslcert
    return ret


def vserver_sslcert_exists(v_name, sc_name, **connection_args):
    """
    Checks if a SSL certificate is tied to a vserver

    CLI Example:

    .. code-block:: bash

        salt '*' netscaler.vserver_sslcert_exists 'vserverName' 'sslCertificateName'
    """
    return _vserver_sslcert_get(v_name, sc_name, **connection_args) is not None


def vserver_sslcert_add(v_name, sc_name, **connection_args):
    """
    Binds a SSL certificate to a vserver

    CLI Example:

    .. code-block:: bash

        salt '*' netscaler.vserver_sslcert_add 'vserverName' 'sslCertificateName'
    """
    ret = True
    if vserver_sslcert_exists(v_name, sc_name, **connection_args):
        return False
    nitro = _connect(**connection_args)
    if nitro is None:
        return False
    sslcert = NSSSLVServerSSLCertKeyBinding()
    sslcert.set_vservername(v_name)
    sslcert.set_certkeyname(sc_name)
    try:
        NSSSLVServerSSLCertKeyBinding.add(nitro, sslcert)
    except NSNitroError as error:
        log.debug(
            "netscaler module error - NSSSLVServerSSLCertKeyBinding.add() failed: %s",
            error,
        )
        ret = False
    _disconnect(nitro)
    return ret


def vserver_sslcert_delete(v_name, sc_name, **connection_args):
    """
    Unbinds a SSL certificate from a vserver

    CLI Example:

    .. code-block:: bash

        salt '*' netscaler.vserver_sslcert_delete 'vserverName' 'sslCertificateName'
    """
    ret = True
    if not vserver_sslcert_exists(v_name, sc_name, **connection_args):
        return False
    nitro = _connect(**connection_args)
    if nitro is None:
        return False
    sslcert = NSSSLVServerSSLCertKeyBinding()
    sslcert.set_vservername(v_name)
    sslcert.set_certkeyname(sc_name)
    try:
        NSSSLVServerSSLCertKeyBinding.delete(nitro, sslcert)
    except NSNitroError as error:
        log.debug(
            "netscaler module error - NSSSLVServerSSLCertKeyBinding.delete()"
            " failed: %s",
            error,
        )
        ret = False
    _disconnect(nitro)
    return ret
