Source code for saltext.vmware.states.nsxt_uplink_profiles

"""
State module for NSX-T uplink profiles
"""
import logging

import salt.utils.dictdiffer

log = logging.getLogger(__name__)

try:
    from saltext.vmware.modules import nsxt_uplink_profiles

    HAS_NSXT_UPLINK_PROFILES = True
except ImportError:
    HAS_NSXT_UPLINK_PROFILES = False


def __virtual__():
    if not HAS_NSXT_UPLINK_PROFILES:
        return False, "'nsxt_uplink_profiles' binary not found on system"
    return "nsxt_uplink_profiles"


def _needs_update(existing_profile, new_teaming, **new_profile_params):
    non_complex_params = ("mtu", "overlay_encap", "required_capabilities", "transport_vlan", "tags")
    for param in non_complex_params:
        param_existing_value = existing_profile.get(param)
        param_new_value = new_profile_params.get(param)
        if not param_existing_value and param_new_value:
            return True
        if param_existing_value and param_new_value and param_existing_value != param_new_value:
            return True
    # checking for updates in lags
    existing_lags = existing_profile.get("lags")
    new_lags = new_profile_params.get("lags")
    if not existing_lags and new_lags:
        return True
    if existing_lags and new_lags:
        sorted_existing_lags = sorted(existing_lags, key=lambda i: i["name"])
        sorted_new_lags = sorted(new_lags, key=lambda i: i["name"])
        if len(sorted_existing_lags) != len(sorted_new_lags):
            return True
        # comparing lag objects one by one
        for i in range(len(sorted_existing_lags)):
            # removing uplinks and id from existing lag as it is nsxt generated and should not be compared with new lag
            existing_current_lag = sorted_existing_lags[i].copy()
            del existing_current_lag["uplinks"]
            del existing_current_lag["id"]
            is_update_required = _are_dictionaries_different(
                existing_current_lag, sorted_new_lags[i]
            )
            if is_update_required:
                return is_update_required

    # checking for updates in named_teamings
    existing_named_teamings = existing_profile.get("named_teamings")
    new_named_teamings = new_profile_params.get("named_teamings")
    if not existing_named_teamings and new_named_teamings:
        return True
    if existing_named_teamings and new_named_teamings:
        sorted_existing_named_teamings = sorted(existing_named_teamings, key=lambda i: i["name"])
        sorted_new_named_teamings = sorted(new_named_teamings, key=lambda i: i["name"])
        if len(sorted_existing_named_teamings) != len(sorted_new_named_teamings):
            return True
        # comparing named_teamings objects one by one
        for i in range(len(sorted_existing_named_teamings)):
            is_update_required = _are_dictionaries_different(
                sorted_existing_named_teamings[i], sorted_new_named_teamings[i]
            )
            if is_update_required:
                return is_update_required

    # checking for updates in teaming. Teaming is a mandatory param, so no need to validate existence
    return _are_dictionaries_different(existing_profile["teaming"], new_teaming)


def _are_dictionaries_different(obj1, obj2):
    # returns True if objects are different, else False
    changes_dict = salt.utils.dictdiffer.deep_diff(obj1, obj2)
    return True if changes_dict else False


[docs]def present( name, hostname, username, password, display_name, teaming, verify_ssl=True, cert=None, cert_common_name=None, lags=None, mtu=None, named_teamings=None, overlay_encap=None, required_capabilities=None, tags=None, transport_vlan=None, description=None, resource_type=None, ): """ Creates or Updates(if present with same display_name) uplink profiles(resource_type:UplinkHostSwitchProfile). Fails if multiple uplink profiles are found with same display_name CLI Example: .. code-block:: bash salt vm_minion nsxt_uplink_profiles.create hostname=nsxt-manager.local username=admin ... .. code-block:: yaml create_uplink_profile: nsxt_uplink_profiles.present: - name: Create uplink profile hostname: {{ pillar['nsxt_manager_hostname'] }} username: {{ pillar['nsxt_manager_username'] }} password: {{ pillar['nsxt_manager_password'] }} cert: {{ pillar['nsxt_manager_certificate'] }} verify_ssl: <False/True> display_name: <uplink profile name> description: <uplink profile description> resource_type: UplinkHostSwitchProfile teaming: active_list: - uplink_name: <Name of the uplink> uplink_type: <PNIC/LAG> - uplink_name: <Name of the uplink> uplink_type: <PNIC/LAG> policy: <FAILOVER_ORDER/LOADBALANCE_SRCID/LOADBALANCE_SRC_MAC> standby_list: - uplink_name: <Name of the uplink> uplink_type: <PNIC/LAG> tags: - tag: <tag-key-1> scope: <tag-value-1> - tag: <tag-key-2> scope: <tag-value-2> mtu: <mtu value> transport_vlan: <vlan_id> lags: - load_balance_algorithm: <SRCMAC/DESTMAC/SRCDESTMAC/SRCDESTIPVLAN/SRCDESTMACIPPORT> mode: <ACTIVE/PASSIVE> name: <name of the lag> number_of_uplinks: <Integer> timeout_type: <SLOW/FAST> - load_balance_algorithm: <SRCMAC/DESTMAC/SRCDESTMAC/SRCDESTIPVLAN/SRCDESTMACIPPORT> mode: <ACTIVE/PASSIVE> name: <name of the lag> number_of_uplinks: <Integer> timeout_type: <SLOW/FAST> named_teamings: - name: <Name of the teaming> active_list: - uplink_name: <Name of the uplink> uplink_type: <PNIC/LAG> - uplink_name: <Name of the uplink> uplink_type: <PNIC/LAG> policy: <FAILOVER_ORDER/LOADBALANCE_SRCID/LOADBALANCE_SRC_MAC> standby_list: - uplink_name: <Name of the uplink> uplink_type: <PNIC/LAG> name Name of the operation hostname The host name of NSX-T manager username Username to connect to NSX-T manager password Password to connect to NSX-T manager display_name The name of the uplink profile resource_type Must be set to the value UplinkHostSwitchProfile. Default is UplinkHostSwitchProfile in Salt Module teaming Default TeamingPolicy associated with this UplinkProfile. Object with following parameters: .. code:: {'standby_list':[],'active_list':[{'uplink_name':'uplink3','uplink_type':'PNIC'}],'policy':'FAILOVER_ORDER'} active_list List of Uplinks used in active list. Array of Uplink objects. .. code:: active_list='[ { "uplink_name": "uplink3", "uplink_type": "PNIC" } ]' Parameters as follows: uplink_name Name of this uplink uplink_type Type of the uplink. PNIC or LAG policy Teaming policy. Required field. Values could be one among FAILOVER_ORDER, LOADBALANCE_SRCID, LOADBALANCE_SRC_MAC standby_list List of Uplinks used in standby list. Array of Uplink objects. .. code:: standby_list=[ { "uplink_name": "uplink2", "uplink_type": "PNIC" } ] Parameters as follows: uplink_name Name of this uplink uplink_type Type of the uplink. PNIC or LAG verify_ssl (Optional) Option to enable/disable SSL verification. Enabled by default. If set to False, the certificate validation is skipped. cert (Optional) Path to the SSL client certificate file to connect to NSX-T manager. The certificate can be retrieved from browser. cert_common_name (Optional) By default, the hostname parameter and the common name in certificate is compared for host name verification. If the client certificate common name and hostname do not match (in case of self-signed certificates), specify the certificate common name as part of this parameter. This value is then used to compare against certificate common name lags (Optional) list of LACP group mtu (Optional) Maximum Transmission Unit used for uplinks named_teamings (Optional) List of named uplink teaming policies that can be used by logical switches. Array of NamedTeamingPolicy overlay_encap (Optional) The protocol used to encapsulate overlay traffic required_capabilities (Optional) List of string tags (Optional) Opaque identifier meaninful to API user. Array of Tag transport_vlan (Optional) VLAN used for tagging Overlay traffic of associated HostSwitch. Type: integer description (Optional) Description for the resource """ ret = {"name": name, "result": True, "comment": "", "changes": {}} uplink_profiles_result = __salt__["nsxt_uplink_profiles.get_by_display_name"]( hostname=hostname, username=username, password=password, verify_ssl=verify_ssl, cert=cert, cert_common_name=cert_common_name, display_name=display_name, ) if "error" in uplink_profiles_result: ret["result"] = False ret["comment"] = "Failed to get uplink profiles from NSX-T Manager : {}".format( uplink_profiles_result["error"] ) return ret result_count = len(uplink_profiles_result.get("results")) if result_count > 1: ret["result"] = False ret["comment"] = ( "Found multiple results(result_count={count}) for uplink profiles with " "display_name {display_name}".format(count=result_count, display_name=display_name) ) return ret if __opts__["test"]: if result_count == 0: ret["result"] = None ret["comment"] = "Uplink profile will be created in NSX-T Manager" else: ret["result"] = None ret["comment"] = "Uplink profile would be updated in NSX-T Manager" return ret if result_count == 0: # create uplink profile log.info( "Creating new uplink profile as no results were found in NSX-T with display_name %s", display_name, ) create_result = __salt__["nsxt_uplink_profiles.create"]( hostname=hostname, username=username, password=password, verify_ssl=verify_ssl, cert=cert, cert_common_name=cert_common_name, display_name=display_name, teaming=teaming, lags=lags, mtu=mtu, named_teamings=named_teamings, overlay_encap=overlay_encap, required_capabilities=required_capabilities, tags=tags, transport_vlan=transport_vlan, description=description, ) if "error" in create_result: ret["result"] = False ret["comment"] = create_result["error"] return ret ret["comment"] = "Created uplink profile {display_name}".format(display_name=display_name) ret["changes"]["new"] = create_result return ret else: # update uplink profile existing_uplink_profile = uplink_profiles_result.get("results")[0] update_required = _needs_update( existing_profile=existing_uplink_profile, new_teaming=teaming, lags=lags, mtu=mtu, named_teamings=named_teamings, overlay_encap=overlay_encap, required_capabilities=required_capabilities, tags=tags, transport_vlan=transport_vlan, description=description, ) if update_required: log.info("Updating uplink profile with display_name %s", display_name) # setting params from existing object back to current object, if missed optional_params_dict = { "lags": lags, "mtu": mtu, "named_teamings": named_teamings, "overlay_encap": overlay_encap, "required_capabilities": required_capabilities, "tags": tags, "transport_vlan": transport_vlan, "description": description, } for key in optional_params_dict.keys(): existing_value = existing_uplink_profile.get(key) if not optional_params_dict.get(key) and existing_value: optional_params_dict[key] = existing_uplink_profile[key] update_result = __salt__["nsxt_uplink_profiles.update"]( hostname=hostname, username=username, password=password, verify_ssl=verify_ssl, cert=cert, cert_common_name=cert_common_name, display_name=display_name, teaming=teaming, uplink_profile_id=existing_uplink_profile["id"], revision=existing_uplink_profile["_revision"], **optional_params_dict ) if "error" in update_result: ret["result"] = False ret["comment"] = update_result["error"] return ret ret["comment"] = "Updated uplink profile {display_name} successfully".format( display_name=display_name ) ret["changes"]["old"] = existing_uplink_profile ret["changes"]["new"] = update_result return ret else: log.info("Update is not required. Uplink profile with same params already exists") ret[ "comment" ] = "Uplink profile already exists with similar params. No action to perform" return ret
[docs]def absent( name, hostname, username, password, display_name, verify_ssl=True, cert=None, cert_common_name=None, ): """ Deletes uplink profile with provided display_name in NSX-T Manager, if present. Fails if multiple uplink profiles are found with same display_name CLI Example: .. code-block:: bash salt vm_minion nsxt_uplink_profiles.absent hostname=nsxt-manager.local username=admin ... .. code-block:: yaml delete_uplink_profile: nsxt_uplink_profiles.absent: - name: <Name of the operation> hostname: {{ pillar['nsxt_manager_hostname'] }} username: {{ pillar['nsxt_manager_username'] }} password: {{ pillar['nsxt_manager_password'] }} cert: {{ pillar['nsxt_manager_certificate'] }} display_name: <display_name of the uplink profile> verify_ssl: <False/True> name Name of the operation to perform hostname The host name of NSX-T manager username Username to connect to NSX-T manager password Password to connect to NSX-T manager display_name Display name of the uplink profile to delete verify_ssl (Optional) Option to enable/disable SSL verification. Enabled by default. If set to False, the certificate validation is skipped. cert (Optional) Path to the SSL certificate file to connect to NSX-T manager. The certificate can be retrieved from browser. cert_common_name (Optional) By default, the hostname parameter and the common name in certificate is compared for host name verification. If the client certificate common name and hostname do not match (in case of self-signed certificates), specify the certificate common name as part of this parameter. This value is then used to compare against certificate common name. """ ret = {"name": name, "result": True, "comment": "", "changes": {}} uplink_profiles_result = __salt__["nsxt_uplink_profiles.get_by_display_name"]( hostname=hostname, username=username, password=password, verify_ssl=verify_ssl, cert=cert, cert_common_name=cert_common_name, display_name=display_name, ) if "error" in uplink_profiles_result: ret["result"] = False ret["comment"] = "Failed to get uplink profiles from NSX-T Manager : {}".format( uplink_profiles_result["error"] ) return ret result_count = len(uplink_profiles_result.get("results")) if result_count > 1: ret["result"] = False ret["comment"] = ( "Found multiple results(result_count={count}) for uplink profiles with " "display_name {display_name}".format(count=result_count, display_name=display_name) ) return ret if __opts__["test"]: if result_count == 0: ret["result"] = None ret[ "comment" ] = "No uplink profile with display_name: {} found in NSX-T Manager".format( display_name ) else: ret["result"] = None ret["comment"] = "Uplink profile with display_name: {} will be deleted".format( display_name ) return ret if result_count == 0: ret["comment"] = "No uplink profile with display_name: {} found in NSX-T Manager".format( display_name ) return ret else: uplink_profile_to_delete = uplink_profiles_result.get("results")[0] delete_result = __salt__["nsxt_uplink_profiles.delete"]( hostname=hostname, username=username, password=password, uplink_profile_id=uplink_profile_to_delete["id"], verify_ssl=verify_ssl, cert=cert, cert_common_name=cert_common_name, ) if "error" in delete_result: ret["result"] = False ret["comment"] = "Failed to delete uplink profile : {}".format(delete_result["error"]) return ret else: ret["comment"] = "Uplink profile with display_name: {} successfully deleted".format( display_name ) ret["changes"]["old"] = uplink_profile_to_delete ret["changes"]["new"] = {} return ret