Passed
Pull Request — master (#84)
by Vinicius
03:41
created

storehouse_to_mongo   A

Complexity

Total Complexity 21

Size/Duplication

Total Lines 114
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 75
dl 0
loc 114
rs 10
c 0
b 0
f 0
wmc 21

6 Functions

Rating   Name   Duplication   Size   Complexity  
A _load_from_file() 0 3 2
A load_boxes_data() 0 3 1
A get_storehouse_dir() 0 2 1
B load_topology_status() 0 29 8
A _list_boxes_files() 0 7 2
B insert_from_topology_status() 0 37 7
1
#!/usr/bin/env python
2
# -*- coding: utf-8 -*-
3
4
import glob
5
import pickle
6
import os
7
from typing import Any, List, Tuple
8
from napps.kytos.topology.db.models import SwitchDoc
9
from napps.kytos.topology.db.models import LinkDoc
10
from napps.kytos.topology.db.client import mongo_client
11
12
client = mongo_client()
13
14
15
def get_storehouse_dir() -> str:
16
    return os.environ["STOREHOUSE_NAMESPACES_DIR"]
17
18
19
def _list_boxes_files(namespace: str, storehouse_dir=get_storehouse_dir()) -> dict:
20
    """List boxes files given the storehouse dir."""
21
    if storehouse_dir.endswith(os.path.sep):
22
        storehouse_dir = storehouse_dir[:-1]
23
    return {
24
        file_name.split(os.path.sep)[-2]: file_name
25
        for file_name in glob.glob(f"{storehouse_dir}/{namespace}**/*", recursive=True)
26
    }
27
28
29
def _load_from_file(file_name) -> Any:
30
    with open(file_name, "rb") as load_file:
31
        return pickle.load(load_file)
32
33
34
def load_boxes_data(namespace: str) -> dict:
35
    """Load boxes data."""
36
    return {k: _load_from_file(v).data for k, v in _list_boxes_files(namespace).items()}
37
38
39
def load_topology_status() -> Tuple[List[dict], List[dict]]:
40
    """Map topology status."""
41
    namespace = "kytos.topology.status"
42
    content = load_boxes_data(namespace)
43
    if namespace not in content:
44
        return ([], [])
45
46
    content = content[namespace]
47
    if "network_status" not in content:
48
        return ([], [])
49
    if "switches" not in content["network_status"]:
50
        return ([], [])
51
52
    links = content["network_status"].get("links", {})
53
54
    switches = []
55
    for switch in content["network_status"]["switches"].values():
56
        switch["_id"] = switch["id"]
57
        if "interfaces" in switch:
58
            switch["interfaces"] = list(switch["interfaces"].values())
59
        switches.append(switch)
60
61
    for link_values in links.values():
62
        if "id" in link_values:
63
            link_values["_id"] = link_values["id"]
64
65
    return (
66
        [SwitchDoc(**switch).dict() for switch in switches],
67
        [LinkDoc(**link).dict() for link in links.values()],
68
    )
69
70
71
def insert_from_topology_status(client=client) -> Tuple[List[str], List[str]]:
72
    """Insert from topology status."""
73
    db = client.napps
74
    switches = db.switches
75
76
    loaded_switches, loaded_links = load_topology_status()
77
    listed_switches = list(
78
        switches.find(
79
            {
80
                "_id": {"$in": [switch["id"] for switch in loaded_switches]},
81
            },
82
            {"_id": 1},
83
        )
84
    )
85
    listed_ids = set([switch["_id"] for switch in listed_switches])
86
87
    insert_switches = []
88
    for switch in loaded_switches:
89
        if switch["id"] not in listed_ids:
90
            insert_switches.append(switch)
91
    if insert_switches:
92
        insert_switches = switches.insert_many(insert_switches).inserted_ids
93
94
    links = db.links
95
    listed_links = list(
96
        links.find({"_id": {"$in": [link["id"] for link in loaded_links]}}, {"_id": 1})
97
    )
98
    link_listed_ids = set([link["_id"] for link in listed_links])
99
100
    insert_links = []
101
    for link in loaded_links:
102
        if link["id"] not in link_listed_ids:
103
            insert_links.append(link)
104
    if insert_links:
105
        insert_links = links.insert_many(insert_links).inserted_ids
106
107
    return (insert_switches, insert_links)
108
109
110
if __name__ == "__main__":
111
    # print(json.dumps(load_topology_status()))
112
    # TODO break as a CLI
113
    print(insert_from_topology_status())
114