Passed
Pull Request — master (#64)
by Vinicius
07:12 queued 04:20
created

build.utils.is_intra_switch_evc()   A

Complexity

Conditions 2

Size

Total Lines 6
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 2

Importance

Changes 0
Metric Value
cc 2
eloc 5
nop 1
dl 0
loc 6
ccs 5
cts 5
cp 1
crap 2
rs 10
c 0
b 0
f 0
1
""" Support function for main.py """
2
3 1
from napps.kytos.telemetry_int import settings
4
5 1
from kytos.core import Controller
6
7 1
from .exceptions import FlowsNotFound, PriorityOverflow, ProxyPortNotFound
8 1
from .kytos_api_helper import get_stored_flows as _get_stored_flows
9 1
from .proxy_port import ProxyPort
10
11
12 1
async def get_found_stored_flows(cookies: list[int] = None) -> dict[int, list[dict]]:
13
    """Get stored flows ensuring that flows are found."""
14
    cookies = cookies or []
15
    stored_flows = await _get_stored_flows()
16
    for cookie, flows in stored_flows.items():
17
        if not flows:
18
            raise FlowsNotFound(get_id_from_cookie(cookie))
19
    return stored_flows
20
21
22 1
def has_int_enabled(evc: dict) -> bool:
23
    """Check if evc has telemetry."""
24 1
    return (
25
        "metadata" in evc
26
        and "telemetry" in evc["metadata"]
27
        and isinstance(evc["metadata"]["telemetry"], dict)
28
        and "enabled" in evc["metadata"]["telemetry"]
29
        and evc["metadata"]["telemetry"]["enabled"]
30
    )
31
32
33 1
def get_evc_unis(evc: dict) -> tuple[dict, dict]:
34
    """Parse evc for unis."""
35 1
    uni_a_split = evc["uni_a"]["interface_id"].split(":")
36 1
    uni_z_split = evc["uni_z"]["interface_id"].split(":")
37 1
    return (
38
        {
39
            "interface_id": evc["uni_a"]["interface_id"],
40
            "tag": evc["uni_a"].get("tag", {}),
41
            "port_number": int(uni_a_split[-1]),
42
            "switch": ":".join(uni_a_split[:-1]),
43
        },
44
        {
45
            "interface_id": evc["uni_z"]["interface_id"],
46
            "tag": evc["uni_z"].get("tag", {}),
47
            "port_number": int(uni_z_split[-1]),
48
            "switch": ":".join(uni_z_split[:-1]),
49
        },
50
    )
51
52
53 1
def get_proxy_port_or_raise(
54
    controller: Controller, intf_id: str, evc_id: str
55
) -> ProxyPort:
56
    """Return a ProxyPort assigned to a UNI or raise."""
57
58 1
    interface = controller.get_interface_by_id(intf_id)
59 1
    if not interface:
60 1
        raise ProxyPortNotFound(evc_id, f"UNI interface {intf_id} not found")
61
62 1
    if "proxy_port" not in interface.metadata:
63 1
        raise ProxyPortNotFound(evc_id, f"proxy_port metadata not found in {intf_id}")
64
65 1
    source_intf = interface.switch.get_interface_by_port_no(
66
        interface.metadata.get("proxy_port")
67
    )
68 1
    if not source_intf:
69
        raise ProxyPortNotFound(
70
            evc_id,
71
            f"proxy_port of {intf_id} source interface not found",
72
        )
73
74 1
    pp = ProxyPort(controller, source_intf)
75
76 1
    if not pp.destination:
77 1
        raise ProxyPortNotFound(
78
            evc_id,
79
            f"proxy_port of {intf_id} isn't looped or destination interface not found",
80
        )
81 1
    return pp
82
83
84 1
def add_to_apply_actions(
85
    instructions: list[dict], new_instruction: dict, position: int
86
):
87
    """Create the actions list"""
88 1
    for instruction in instructions:
89 1
        if instruction["instruction_type"] == "apply_actions":
90 1
            instruction["actions"].insert(position, new_instruction)
91 1
    return instructions
92
93
94 1
def get_cookie(evc_id: str, cookie_prefix: int) -> int:
95
    """Return the cookie integer from evc id.
96
97
    cookie_prefix is supposed to be the reserved byte value that
98
    mef_eline or telemetry_int uses.
99
    """
100 1
    return int(evc_id, 16) + (cookie_prefix << 56)
101
102
103 1
def get_id_from_cookie(cookie: int) -> str:
104
    """Return the evc id given a cookie value."""
105 1
    evc_id = cookie & 0xFFFFFFFFFFFFFF
106 1
    return f"{evc_id:x}"
107
108
109 1
def is_intra_switch_evc(evc):
110
    """Returns if EVC is intra-switch (two UNIs on the same switch)"""
111 1
    uni_a, uni_z = get_evc_unis(evc)
112 1
    if uni_a["switch"] == uni_z["switch"]:
113 1
        return True
114 1
    return False
115
116
117 1
def modify_actions(actions: list[dict], actions_to_change: list[str], remove=True):
118
    """Change the current actions
119
    If remove == True, remove actions_to_change from actions.
120
    If remove == False, keep actions_to_change, remove everything else
121
    Args:
122
        actions = current list of actions on a flow
123
        actions_to_change = list of actions as strings
124
        remove = boolean
125
    Return
126
        actions
127
    """
128 1
    del_indexes = set()
129 1
    for index, action in enumerate(actions):
130 1
        if remove:
131 1
            if action["action_type"] in actions_to_change:
132 1
                del_indexes.add(index)
133
        else:
134 1
            if action["action_type"] not in actions_to_change:
135 1
                del_indexes.add(index)
136 1
    return [action for i, action in enumerate(actions) if i not in del_indexes]
137
138
139 1
def set_priority(flow: dict, evc_id: str = "") -> dict:
140
    """Find a suitable priority number. EP031 describes 100 as the addition."""
141 1
    if flow["flow"]["priority"] + 100 < (2**16 - 2):
142 1
        flow["flow"]["priority"] += 100
143
    elif flow["flow"]["priority"] + 1 < (2**16 - 2):
144
        flow["flow"]["priority"] += 1
145
    else:
146
        raise PriorityOverflow(evc_id, f"Flow {flow} would overflow max priority")
147 1
    return flow
148
149
150 1
def set_owner(flow: dict) -> dict:
151
    """Set flow owner."""
152 1
    flow["flow"]["owner"] = "telemetry_int"
153 1
    return flow
154
155
156 1
def get_new_cookie(cookie: int, cookie_prefix=settings.INT_COOKIE_PREFIX) -> int:
157
    """Convert from mef-eline cookie by replacing the most significant byte."""
158 1
    return (cookie & 0xFFFFFFFFFFFFFF) + (cookie_prefix << 56)
159
160
161 1
def set_new_cookie(flow: dict) -> dict:
162
    """Set new cookie."""
163 1
    flow["flow"]["cookie"] = get_new_cookie(
164
        flow["flow"]["cookie"], cookie_prefix=settings.INT_COOKIE_PREFIX
165
    )
166 1
    return flow
167
168
169 1
def set_instructions_from_actions(flow: dict) -> dict:
170
    """Get intructions or convert from actions."""
171 1
    if "instructions" in flow["flow"]:
172 1
        return flow
173
174 1
    instructions = [
175
        {
176
            "instruction_type": "apply_actions",
177
            "actions": flow["flow"].get("actions", []),
178
        }
179
    ]
180 1
    flow["flow"].pop("actions", None)
181 1
    flow["flow"]["instructions"] = instructions
182
    return flow
183