Passed
Pull Request — master (#245)
by
unknown
04:56
created

001_retire_vlans   A

Complexity

Total Complexity 6

Size/Duplication

Total Lines 148
Duplicated Lines 12.16 %

Importance

Changes 0
Metric Value
eloc 111
dl 18
loc 148
rs 10
c 0
b 0
f 0
wmc 6

2 Functions

Rating   Name   Duplication   Size   Complexity  
A disable_evc() 0 10 3
A enable_evc() 0 10 3

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

1
from collections import defaultdict
2
3
import kytos.core.tag_ranges as range_helpers
4
5
# Change to False so this script makes changes
6
DRY_RUN = True
7
# Modify with VLAN ranges being retired from use
8
RETIRED_VLANS = [[4095, 4095]]
9
10
def disable_evc(evc_id):
11
    import httpx
12
    MEF_ELINE_URL = 'http://localhost:8181/api/kytos/mef_eline/v2'
13
    url = f"{MEF_ELINE_URL}/evc/{evc_id}"
14
    data = {
15
        "enabled": False
16
    }
17
    res = httpx.request("PATCH", url, json=data, timeout=10)
18
    if res.is_server_error or res.status_code in {424, 404, 400}:
19
        print(f"Error disabling EVC {evc_id}: {res.text}")
20
21
def enable_evc(evc_id):
22
    import httpx
23
    MEF_ELINE_URL = 'http://localhost:8181/api/kytos/mef_eline/v2'
24
    url = f"{MEF_ELINE_URL}/evc/{evc_id}"
25
    data = {
26
        "enabled": True
27
    }
28
    res = httpx.request("PATCH", url, json=data, timeout=30)
29
    if res.is_server_error or res.status_code in {424, 404, 400}:
30
        print(f"Error disabling EVC {evc_id}: {res.text}")
31
32
mef_eline = controller.napps[("kytos", "mef_eline")]
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable controller does not seem to be defined.
Loading history...
33
of_lldp = controller.napps[('kytos', 'of_lldp')]
34
evcs = {
35
    evc_id: evc.as_dict()
36
    for evc_id, evc in mef_eline.circuits.items()
37
    if not evc.archived
38
}
39
40
in_use_tags = defaultdict(list)
41
for evc_id, evc in evcs.items():
42
    for link in evc["current_path"]:
43
        svlan = link["metadata"]["s_vlan"]["value"]
44
        intfa = link["endpoint_a"]["id"]
45
        intfb = link["endpoint_b"]["id"]
46
        in_use_tags[intfa].append((svlan, evc_id))
47
        in_use_tags[intfb].append((svlan, evc_id))
48
    for link in evc["failover_path"]:
49
        svlan = link["metadata"]["s_vlan"]["value"]
50
        intfa = link["endpoint_a"]["id"]
51
        intfb = link["endpoint_b"]["id"]
52
        in_use_tags[intfa].append((svlan, evc_id))
53
        in_use_tags[intfb].append((svlan, evc_id))
54
55
    for uni in ("uni_a", "uni_z"):
56
        intf_id = evc[uni]["interface_id"]
57 View Code Duplication
        if (
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
58
            "tag" in evc[uni]
59
            and evc[uni]["tag"]
60
            and "tag_type" in evc[uni]["tag"]
61
            and evc[uni]["tag"]["tag_type"] in ("vlan", 1)
62
        ):
63
            tag = evc[uni]["tag"]["value"]
64
            if isinstance(tag, int):
65
                in_use_tags[intf_id].append((tag, evc_id))
66
            elif isinstance(tag, list):
67
                for tag_item in tag:
68
                    if isinstance(tag_item, int):
69
                        in_use_tags[intf_id].append((tag_item, evc_id))
70
                    elif isinstance(tag_item, list) and len(tag_item) == 1:
71
                        in_use_tags[intf_id].append((tag_item[0], evc_id))
72
                    elif isinstance(tag_item, list) and len(tag_item) == 2:
73
                        for val in range(tag_item[0], tag_item[1]+1):
74
                            in_use_tags[intf_id].append((val, evc_id))
75
76
switch_rm_flows = {}
77
78
evc_disable_set = set()
79
80
dry_run_key = "WILL" if not DRY_RUN else "WOULD"
81
82
print("Checking EVCs for vlan usage...")
83
84
# Find all evcs to temporarily disable
85
for intf_id in in_use_tags:
86
    for tag, evc_id in in_use_tags[intf_id]:
87
        if evc_id in evc_disable_set:
88
            continue
89
        intersect = range_helpers.range_intersection([[tag, tag]], RETIRED_VLANS)
90
        intersect = list(intersect)
91
        if intersect:
92
            print(
93
                f"EVC {evc_id} is using s_vlan {intersect} which is pending retirement, {dry_run_key} temporarily disable it..."
94
            )
95
            evc_disable_set.add(evc_id)
96
97
# Disable EVCs
98
if not DRY_RUN and evc_disable_set:
99
    print("Disabling EVCs...")
100
    for evc_id in evc_disable_set:
101
            disable_evc(evc_id)
102
103
# Retire the given vlan ranges
104
105
if not DRY_RUN:
106
    print("Clearing vlan from tag_ranges and available_tags")
107
else:
108
    print("Checking interfaces for vlan usage...")
109
110
for dpid in list(controller.switches.keys()):
111
    switch = controller.get_switch_by_dpid(dpid)
112
    for intf_id, intf in switch.interfaces.copy().items():
113
        with intf._tag_lock:
114
            used_tags = range_helpers.range_difference(
115
                intf.tag_ranges['vlan'], intf.available_tags['vlan']
116
            )
117
            new_range = range_helpers.range_difference(
118
                intf.tag_ranges['vlan'], RETIRED_VLANS
119
            )
120
            missing = range_helpers.range_difference(
121
                used_tags, new_range
122
            )
123
            if missing:
124
                if not DRY_RUN:
125
                    print(
126
                        f"WARNING: Interface {dpid} {intf_id} still has the vlans {missing} in use."
127
                    )
128
                else:
129
                    print(
130
                        f"Interface {dpid} {intf_id} has the vlans {missing} in use."
131
                    )
132
                continue
133
            if not DRY_RUN:
134
                new_available_tags = range_helpers.range_difference(
135
                    new_range, used_tags
136
                )
137
                intf.available_tags['vlan'] = new_available_tags
138
                intf.tag_ranges['vlan'] = new_range
139
140
# Re-enable the evcs
141
142
if not DRY_RUN and evc_disable_set:
143
    print("Re-enabling EVCs...")
144
    for evc_id in evc_disable_set:
145
            enable_evc(evc_id)
146
147
print("Finished!")
148