Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[minor_change] Add ndo_tenant_custom_qos_policy for tenant Custom QoS configuration. (DCNE-127) #571

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
28 changes: 28 additions & 0 deletions plugins/module_utils/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -211,3 +211,31 @@

ORIGINATE_DEFAULT_ROUTE = {"only": "only", "in_addition": "inAddition", "": ""}
L3OUT_ROUTING_PROTOCOLS = {"bgp": ["bgp"], "ospf": ["ospf"], "bgpOspf": ["bgp", "ospf"], None: [None], "": None, "bgpospf": "bgpOspf", "ospfbgp": "bgpOspf"}

TARGET_COS_MAP = {
"background": "cos0",
"best_effort": "cos1",
"excellent_effort": "cos2",
"critical_applications": "cos3",
"video": "cos4",
"voice": "cos5",
"internetwork_control": "cos6",
"network_control": "cos7",
"unspecified": "cos8",
}

DSCP_KEYS_FORMAT_MAP = {
"dscp_from": ["dscpFrom", TARGET_DSCP_MAP],
"dscp_to": ["dscpTo", TARGET_DSCP_MAP],
"dscp_target": ["dscpTarget", TARGET_DSCP_MAP],
"target_cos": ["targetCos", TARGET_COS_MAP],
"qos_priority": "priority",
}

DOT1P_KEYS_FORMAT_MAP = {
"dot1p_from": ["dot1pFrom", TARGET_COS_MAP],
"dot1p_to": ["dot1pTo", TARGET_COS_MAP],
"dscp_target": ["dscpTarget", TARGET_DSCP_MAP],
"target_cos": ["targetCos", TARGET_COS_MAP],
"qos_priority": "priority",
}
81 changes: 80 additions & 1 deletion plugins/module_utils/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ def append_update_ops_data(ops, existing_data, update_path, replace_data=None, r
replace_data = {
("name"): "new_name",
"description": "new_description",
("ospfIntfPol"): dict(ifControl=dict(adminState="disbaled"), cost=0),
("ospfIntfPol"): dict(ifControl=dict(adminState="disbaled"), cost=0)),
}
remove_data = [("bfdMultiHopPol", "ifControl", "adminState"), "bfdPol"]

Expand Down Expand Up @@ -145,3 +145,82 @@ def recursive_delete(data, path, keys):

for key in remove_data:
recursive_delete(existing_data, update_path, key if isinstance(key, tuple) else (key,))


def format_list_dict(list_dict, keys_map):
gmicol marked this conversation as resolved.
Show resolved Hide resolved
"""
Convert an Python list of dictionaries into its equivalent NDO API format.
All keys must be defined in the keys map even if no conversion is needed for some keys.

:param list_dict: The Python list of dictionaries to format. Can be an empty List or None -> List
:param keys_map: The mapping from the Ansible argument's keys to NDO API keys. Can also include the map between values -> Dict
:return: The formatted list of dictionaries -> Dict

Sample Input Data:
---------------------
REDUCED_TARGET_COS_MAP = {
"background": "cos0",
"best_effort": "cos1",
"excellent_effort": "cos2",
}

REDUCED_TARGET_DSCP_MAP = {
"af11": "af11",
"cs0": "cs0",
"voice_admit": "voiceAdmit",
}

COS_KEYS_FORMAT_MAP = {
"dot1p_from": ["dot1pFrom", REDUCED_TARGET_COS_MAP],
"dot1p_to": ["dot1pTo", REDUCED_TARGET_COS_MAP],
"dscp_target": ["dscpTarget", REDUCED_TARGET_DSCP_MAP],
"target_cos": ["targetCos", REDUCED_TARGET_COS_MAP],
"qos_priority": "priority",
}

ansible_cos_mappings = [
{
"dot1p_from": "background",
"dot1p_to": "best_effort",
"dscp_target": "voice_admit",
"target_cos": "excellent_effort",
"qos_priority": "level1",
}
]

formatted_cos_mappings = format_list_dict(ansible_cos_mappings, COS_KEYS_FORMAT_MAP)

Output Data:
---------------------
[
{
"dot1pFrom": "cos0",
"dot1pTo": "cos1",
"dscpTarget": "voiceAdmit",
"targetCos": "cos2",
"priority": "level1",
}
]
"""
if isinstance(list_dict, list) and isinstance(keys_map, dict):

def format_dict(d): # format individual dictionary to its equivalent NDO API format
formatted_dict = {}
if isinstance(d, dict):
for key, value in keys_map.items():
gmicol marked this conversation as resolved.
Show resolved Hide resolved
# keys_map can have values of type list including the API key string and the map conversion for values
if isinstance(value, list):
formatted_dict[value[0]] = value[1].get(d.get(key))
else:
formatted_dict[value] = d.get(key)
else:
raise TypeError("items in list_dict must be dictionaries.")
return formatted_dict

return [format_dict(d) for d in list_dict]

elif list_dict is not None and not isinstance(list_dict, list):
raise TypeError("list_dict can either be a list of dictionaries, an empty List or None.")

elif not isinstance(keys_map, dict):
raise TypeError("keys_map must be a dictionary.")
Loading
Loading