ffmap-backend/ffmap/outputs/d3json.py

92 lines
2.9 KiB
Python
Raw Normal View History

2014-07-07 23:27:21 +02:00
import json
from datetime import datetime
2014-07-07 23:27:21 +02:00
__all__ = ["Exporter"]
class CustomJSONEncoder(json.JSONEncoder):
"""
JSON encoder that uses an object's __json__() method to convert it
to something JSON-compatible.
2014-07-07 23:27:21 +02:00
"""
def default(self, obj):
try:
return obj.__json__()
except AttributeError:
pass
return super().default(obj)
class Output:
2014-07-07 23:27:21 +02:00
def __init__(self, filepath="nodes.json"):
self.filepath = filepath
@staticmethod
def generate(nodedb):
indexes = {}
nodes = []
count = 0
for node in set(nodedb.values()):
node_export = node.export()
node_export["flags"] = {
"gateway": "vpn" in node and node["vpn"],
"client": False,
"online": True
}
nodes.append(node_export)
2014-07-07 23:27:21 +02:00
indexes[node.id] = count
count += 1
links = {}
2014-07-07 23:27:21 +02:00
for node in set(nodedb.values()):
for neighbor in node.get("neighbors", []):
key = (neighbor["neighbor"].id, node.id)
rkey = tuple(reversed(key))
if rkey in links:
links[rkey]["quality"] += ","+neighbor["metric"]
else:
links[key] = {
2014-07-07 23:27:21 +02:00
"source": indexes[node.id],
"target": indexes[neighbor["neighbor"].id],
"quality": neighbor["metric"],
"type": "vpn" if neighbor["neighbor"]["vpn"] or node["vpn"] else None,
2014-07-07 23:27:21 +02:00
"id": "-".join((node.id, neighbor["neighbor"].id)),
}
2014-09-06 13:48:03 +02:00
clientcount = 0
for client in node.get("clients", []):
2014-09-06 13:48:03 +02:00
nodes.append({
"id": "%s-%s" % (node.id, clientcount),
"flags": {
"client": True,
"online": True,
"gateway": False
}
})
indexes[client] = count
links[(node.id, client)] = {
"source": indexes[node.id],
"target": indexes[client],
"quality": "TT",
"type": "client",
2014-09-06 13:48:03 +02:00
"id": "%s-%i" % (node.id, clientcount),
}
2014-09-06 13:48:03 +02:00
count += 1
clientcount += 1
2014-07-07 23:27:21 +02:00
return {
"nodes": nodes,
"links": list(links.values()),
"meta": {
"timestamp": datetime.utcnow()
.replace(microsecond=0)
.isoformat()
}
2014-07-07 23:27:21 +02:00
}
def output(self, nodedb):
2014-07-07 23:27:21 +02:00
with open(self.filepath, "w") as nodes_json:
json.dump(
self.generate(nodedb),
nodes_json,
cls=CustomJSONEncoder
)