Passed
Pull Request — master (#245)
by
unknown
03:22
created

001_retire_vlans   A

Complexity

Total Complexity 6

Size/Duplication

Total Lines 153
Duplicated Lines 11.76 %

Importance

Changes 0
Metric Value
wmc 6
eloc 115
dl 18
loc 153
rs 10
c 0
b 0
f 0

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
topology = controller.napps[('kytos', 'topology')]
35
36
evcs = {
37
    evc_id: evc.as_dict()
38
    for evc_id, evc in mef_eline.circuits.items()
39
    if not evc.archived
40
}
41
42
in_use_tags = defaultdict(list)
43
for evc_id, evc in evcs.items():
44
    for link in evc["current_path"]:
45
        svlan = link["metadata"]["s_vlan"]["value"]
46
        intfa = link["endpoint_a"]["id"]
47
        intfb = link["endpoint_b"]["id"]
48
        in_use_tags[intfa].append((svlan, evc_id))
49
        in_use_tags[intfb].append((svlan, evc_id))
50
    for link in evc["failover_path"]:
51
        svlan = link["metadata"]["s_vlan"]["value"]
52
        intfa = link["endpoint_a"]["id"]
53
        intfb = link["endpoint_b"]["id"]
54
        in_use_tags[intfa].append((svlan, evc_id))
55
        in_use_tags[intfb].append((svlan, evc_id))
56
57
    for uni in ("uni_a", "uni_z"):
58
        intf_id = evc[uni]["interface_id"]
59 View Code Duplication
        if (
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
60
            "tag" in evc[uni]
61
            and evc[uni]["tag"]
62
            and "tag_type" in evc[uni]["tag"]
63
            and evc[uni]["tag"]["tag_type"] in ("vlan", 1)
64
        ):
65
            tag = evc[uni]["tag"]["value"]
66
            if isinstance(tag, int):
67
                in_use_tags[intf_id].append((tag, evc_id))
68
            elif isinstance(tag, list):
69
                for tag_item in tag:
70
                    if isinstance(tag_item, int):
71
                        in_use_tags[intf_id].append((tag_item, evc_id))
72
                    elif isinstance(tag_item, list) and len(tag_item) == 1:
73
                        in_use_tags[intf_id].append((tag_item[0], evc_id))
74
                    elif isinstance(tag_item, list) and len(tag_item) == 2:
75
                        for val in range(tag_item[0], tag_item[1]+1):
76
                            in_use_tags[intf_id].append((val, evc_id))
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
            old_range = intf.tag_ranges['vlan']
115
            used_tags = range_helpers.range_difference(
116
                old_range, intf.available_tags['vlan']
117
            )
118
            new_range = range_helpers.range_difference(
119
                old_range, RETIRED_VLANS
120
            )
121
            missing = range_helpers.range_difference(
122
                used_tags, new_range
123
            )
124
            if missing:
125
                if not DRY_RUN:
126
                    print(
127
                        f"WARNING: Interface {dpid} {intf_id} still has the vlans {missing} in use. Can't retire vlans."
128
                    )
129
                else:
130
                    print(
131
                        f"Interface {dpid} {intf_id} has the vlans {missing} in use."
132
                    )
133
                continue
134
            change = range_helpers.range_difference(
135
                old_range, new_range
136
            )
137
            if not DRY_RUN and change:
138
                new_available_tags = range_helpers.range_difference(
139
                    new_range, used_tags
140
                )
141
                intf.available_tags['vlan'] = new_available_tags
142
                intf.tag_ranges['vlan'] = new_range
143
                topology.handle_on_interface_tags(intf)
144
145
# Re-enable the evcs
146
147
if not DRY_RUN and evc_disable_set:
148
    print("Re-enabling EVCs...")
149
    for evc_id in evc_disable_set:
150
            enable_evc(evc_id)
151
152
print("Finished!")
153