diff options
author | makefu <root@pigstarter.de> | 2015-09-09 14:41:38 +0200 |
---|---|---|
committer | makefu <root@pigstarter.de> | 2015-09-09 14:41:38 +0200 |
commit | 05bf2c8be209e619f8c9e727fd1353198b042642 (patch) | |
tree | 4f7a9439137fe78f979b235666a3533f9e249eca | |
parent | e9e7d6baf986488c43d418887f6cf95f5d896189 (diff) |
begin packaging of tinc_stats
19 files changed, 192 insertions, 141 deletions
diff --git a/retiolum/scripts/adv_graphgen/.gitignore b/retiolum/scripts/adv_graphgen/.gitignore new file mode 100644 index 00000000..fbee25a5 --- /dev/null +++ b/retiolum/scripts/adv_graphgen/.gitignore @@ -0,0 +1,5 @@ +bin/ +include/ +lib/ +*.egg-info/ +GeoLiteCity.dat diff --git a/retiolum/scripts/adv_graphgen/README b/retiolum/scripts/adv_graphgen/README.md index 082e0f2b..082e0f2b 100644 --- a/retiolum/scripts/adv_graphgen/README +++ b/retiolum/scripts/adv_graphgen/README.md diff --git a/retiolum/scripts/adv_graphgen/all_the_graphs.sh b/retiolum/scripts/adv_graphgen/all_the_graphs.sh deleted file mode 100755 index 9f3bf82b..00000000 --- a/retiolum/scripts/adv_graphgen/all_the_graphs.sh +++ /dev/null @@ -1,16 +0,0 @@ -#!/bin/bash - -( - echo "`date` begin all graphs" >> /tmp/build_graph - cd $(dirname $(readlink -f $0)) - PATH=$PATH:../../../util/bin/ - EXTERNAL_FOLDER=/var/www/euer.krebsco.de/graphs/retiolum - INTERNAL_FOLDER=/var/www/euer/graphs/retiolum - begin=`timer` - export GEOCTIYDB="$PWD/GeoLiteCity.dat" - (python tinc_stats/Log2JSON.py | python tinc_stats/Geo.py > $INTERNAL_FOLDER/marker.json)& - (./anonytize.sh $EXTERNAL_FOLDER && echo "`date` anonytize done" >> /tmp/build_graph)& - (./sanitize.sh $INTERNAL_FOLDER && echo "`date` sanitize done" >> /tmp/build_graph)& -# wait - echo "`date` end all graphs" >> /tmp/build_graph -)& diff --git a/retiolum/scripts/adv_graphgen/anonytize.sh b/retiolum/scripts/adv_graphgen/anonytize.sh deleted file mode 100755 index 04a68869..00000000 --- a/retiolum/scripts/adv_graphgen/anonytize.sh +++ /dev/null @@ -1,29 +0,0 @@ -#!/bin/sh -set -euf -cd $(dirname `readlink -f $0`) -GRAPH_SETTER1=dot -GRAPH_SETTER2=circo -GRAPH_SETTER3='neato -Goverlap=prism ' -GRAPH_SETTER4=sfdp -TYPE=svg -TYPE2=png -OPENER=/bin/true -DOTFILE=`mktemp --suffix=anon` -trap 'rm $DOTFILE' INT TERM KILL EXIT -sudo -E python tinc_stats/Log2JSON.py |\ - python tinc_stats/Graph.py anonymous> $DOTFILE - - -i=1 -for setter in dot circo 'neato -Goverlap=prism ' sfdp -do - tmpgraph=`mktemp --tmpdir=$1` - $setter -T$TYPE -o $tmpgraph $DOTFILE - chmod go+rx $tmpgraph - mv $tmpgraph $1/retiolum_$i.$TYPE - i=`expr $i + 1` -done -convert $1/retiolum_1.$TYPE $1/retiolum_1.$TYPE2 -#convert -resize 20% $1/retiolum_2.$TYPE $1/retiolum_2.$TYPE2 -#convert -resize 20% $1/retiolum_3.$TYPE $1/retiolum_3.$TYPE2 -#convert -resize 20% $1/retiolum_4.$TYPE $1/retiolum_4.$TYPE2 diff --git a/retiolum/scripts/adv_graphgen/sanitize.sh b/retiolum/scripts/adv_graphgen/sanitize.sh deleted file mode 100755 index f7d0e7e7..00000000 --- a/retiolum/scripts/adv_graphgen/sanitize.sh +++ /dev/null @@ -1,31 +0,0 @@ -#!/bin/sh -set -euf -cd $(dirname `readlink -f $0`) -GRAPH_SETTER1=dot -GRAPH_SETTER2=circo -GRAPH_SETTER3='neato -Goverlap=prism ' -GRAPH_SETTER4=sfdp -TYPE=svg -TYPE2=png -OPENER=/bin/true -DOTFILE=`mktemp --suffix=san` -trap 'rm $DOTFILE' INT TERM KILL EXIT -sudo -E python tinc_stats/Log2JSON.py |\ - python tinc_stats/Graph.py complete > $DOTFILE - - -i=1 -for setter in dot circo 'neato -Goverlap=prism ' sfdp -do - tmpgraph=`mktemp --tmpdir=$1` - $setter -T$TYPE -o $tmpgraph $DOTFILE - chmod go+rx $tmpgraph - mv $tmpgraph $1/retiolum_$i.$TYPE - i=`expr $i + 1` -done - -convert $1/retiolum_1.$TYPE $1/retiolum_1.$TYPE2 -#convert -resize 20% $1/retiolum_2.$TYPE $1/retiolum_2.$TYPE2 -#convert -resize 20% $1/retiolum_3.$TYPE $1/retiolum_3.$TYPE2 -#convert -resize 20% $1/retiolum_4.$TYPE $1/retiolum_4.$TYPE2 -rm $DOTFILE diff --git a/retiolum/scripts/adv_graphgen/scripts/all-the-graphs b/retiolum/scripts/adv_graphgen/scripts/all-the-graphs new file mode 100755 index 00000000..3368d145 --- /dev/null +++ b/retiolum/scripts/adv_graphgen/scripts/all-the-graphs @@ -0,0 +1,13 @@ +#!/bin/bash + +EXTERNAL_FOLDER=${EXTERNAL_FOLDER:-/var/www/euer.krebsco.de/graphs/retiolum} +INTERNAL_FOLDER=${INTERNAL_FOLDER:-/var/www/euer/graphs/retiolum} +GEOCTIYDB="${GEOCITYDB:-}" + +if test -n "$GEOCITYDB";then + # creates a marker file + # TODO: copy map.html from + tinc-stats2json | add-geodata > "$INTERNAL_FOLDER/marker.json" +fi +build-graphs anonymous "$EXTERNAL_FOLDER" +build-graphs complete "$INTERNAL_FOLDER" diff --git a/retiolum/scripts/adv_graphgen/scripts/build-graphs b/retiolum/scripts/adv_graphgen/scripts/build-graphs new file mode 100755 index 00000000..3eb675ec --- /dev/null +++ b/retiolum/scripts/adv_graphgen/scripts/build-graphs @@ -0,0 +1,27 @@ +#!/bin/sh +set -euf +mode=${1?arg1 must be either 'anonymous' or 'complete'} +out=${2?arg2 must be set to an outdir} +# for creating all the graphs +TYPE=svg +# for creating real pictures +TYPE2=png + +DOTFILE=`mktemp` +trap 'rm "$DOTFILE"' INT TERM KILL EXIT + +tinc-stats2json | tinc-build-graph "$mode" > "$DOTFILE" + +i=1 +for setter in dot circo 'neato -Goverlap=prism ' sfdp +do + tmpgraph=`mktemp --tmpdir=$1` + # first build, then move to avoid half-built graphs + "$setter" -T$TYPE -o "$tmpgraph" "$DOTFILE" ||: + chmod go+rx "$tmpgraph" + mv "$tmpgraph" "$1/retiolum_$i.$TYPE" + i=`expr $i + 1` +done + +convert -limit memory 32Mib -limit map 64Mib "$out/retiolum_1.$TYPE" "$out/retiolum_1.$TYPE2" +rm "$DOTFILE" diff --git a/retiolum/scripts/adv_graphgen/setup.py b/retiolum/scripts/adv_graphgen/setup.py new file mode 100644 index 00000000..84597def --- /dev/null +++ b/retiolum/scripts/adv_graphgen/setup.py @@ -0,0 +1,41 @@ +import sys +from setuptools import setup + +setup( + name='tinc_graphs', + version='0.2.3', + + description='Create Graphs from tinc Stats', + long_description=open("README.md").read(), + license='WTFPL', + url='http://krebsco.de/', + download_url='https://pypi.python.org/pypi/tinc_graphs/', + + author='krebs', + author_email='spam@krebsco.de', + # you will also need graphviz and imagemagick + install_requires = [ 'pygeoip' ], + + packages=['tinc_graphs'], + entry_points={ + 'console_scripts' : [ + 'tinc-stats2json = tinc_graphs.Log2JSON:main', + 'tinc-build-graph = tinc_graphs.Graph:main', + 'add-geodata = tinc_graphs.Geo:main', + 'tinc-availability-stats = tinc_graphs.Availability:generate_stats', + ] + }, + + classifiers=[ + "Intended Audience :: Developers", + "Natural Language :: English", + "Operating System :: POSIX :: Linux", + "Development Status :: 3 - Alpha", + "Programming Language :: Python", + "Programming Language :: Python :: 2.7", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.4", + "Programming Language :: Python :: Implementation :: CPython", + ], +) + diff --git a/retiolum/scripts/adv_graphgen/tinc_graphs.nix b/retiolum/scripts/adv_graphgen/tinc_graphs.nix new file mode 100644 index 00000000..b45fde13 --- /dev/null +++ b/retiolum/scripts/adv_graphgen/tinc_graphs.nix @@ -0,0 +1,25 @@ +with import <nixpkgs> {}; +# nix-build Reaktor.nix +# result/bin/reaktor +## or in your env +# nix-env -i -f tinc_graphs.nix + +buildPythonPackage rec { + name = "tinc_graphs-${version}"; + version = "0.2.6"; + propagatedBuildInputs = with pkgs;[ + pythonPackages.docopt + graphviz + imagemagick + pythonPackages.pygeoip + ]; + src = fetchurl { + url = ""; + sha256 = "1dksw1s1n2hxvnga6pygkr174dywncr0wiggkrkn1srbn2amh1c2"; + }; + meta = { + homepage = http://krebsco.de/; + description = "Create Graphs from Tinc Stats"; + license = stdenv.lib.licenses.wtfpl; + }; +} diff --git a/retiolum/scripts/adv_graphgen/tinc_stats/Availability.py b/retiolum/scripts/adv_graphgen/tinc_graphs/Availability.py index 66defa44..42f28ef9 100755 --- a/retiolum/scripts/adv_graphgen/tinc_stats/Availability.py +++ b/retiolum/scripts/adv_graphgen/tinc_graphs/Availability.py @@ -1,14 +1,14 @@ #!/usr/bin/python # -*- coding: utf8 -*- -import sys,json +import sys,json,os """ TODO: Refactoring needed to pull the edges out of the node structures again, it should be easier to handle both structures""" -DUMP_FILE = "/krebs/db/availability" +DUMP_FILE = os.environment.get("AVAILABILITY_FILE","tinc-availability.json") +hostpath=os.environment.get("TINC_HOSTPATH", "/etc/tinc/retiolum/hosts") def get_all_nodes(): - import os - return os.listdir("/etc/tinc/retiolum/hosts") + return os.listdir(hostpath) def generate_stats(): """ Generates availability statistics of the network and nodes @@ -21,11 +21,13 @@ def generate_stats(): jlines.append(json.loads(line)) f.close() except Exception as e: - pass + print("Unable to open and parse Availability DB: {} (override with AVAILABILITY_FILE)".format(DUMP_FILE) + sys.exit(1) + all_nodes = {} for k in get_all_nodes(): all_nodes[k] = get_node_availability(k,jlines) - print ( json.dumps(all_nodes)) + print (json.dumps(all_nodes)) def get_node_availability(name,jlines): """ calculates the node availability by reading the generated dump file diff --git a/retiolum/scripts/adv_graphgen/tinc_stats/BackwardsReader.py b/retiolum/scripts/adv_graphgen/tinc_graphs/BackwardsReader.py index 6bdbf43c..6bdbf43c 100644 --- a/retiolum/scripts/adv_graphgen/tinc_stats/BackwardsReader.py +++ b/retiolum/scripts/adv_graphgen/tinc_graphs/BackwardsReader.py diff --git a/retiolum/scripts/adv_graphgen/tinc_stats/Geo.py b/retiolum/scripts/adv_graphgen/tinc_graphs/Geo.py index 038ca9c0..78add918 100755 --- a/retiolum/scripts/adv_graphgen/tinc_stats/Geo.py +++ b/retiolum/scripts/adv_graphgen/tinc_graphs/Geo.py @@ -1,9 +1,20 @@ #!/usr/bin/python3 # -*- coding: utf8 -*- import sys,json,os -from Graph import delete_unused_nodes,resolve_myself +from .Graph import delete_unused_nodes,resolve_myself GEODB=os.environ.get("GEOCITYDB","GeoLiteCity.dat") +def copy_map(): + from shutil import copytree + from os.path import dirname,join,realpath + if len(sys.argv) != 2 or sys.argv[1] == "--help" : + print("usage: {} <destination>".format(sys.argv[0]) + print(" copies the map.html file to the <destination>") + sys.exit(1) + dstdir=sys.argv[1] + copytree(realpath(join(dirname(__file__),'static/map.html')),dstdir) + + def add_geo(nodes): from pygeoip import GeoIP gi = GeoIP(GEODB) @@ -14,8 +25,8 @@ def add_geo(nodes): except Exception as e: sys.stderr.write(str(e)) sys.stderr.write("Cannot determine GeoData for %s\n"%k) - return nodes + def add_coords_to_edges(nodes): from pygeoip import GeoIP gi = GeoIP(GEODB) @@ -48,7 +59,19 @@ def add_jitter(nodes): except Exception as e: pass return nodes -if __name__ == "__main__": +def main(): import json - nodes = add_jitter(add_coords_to_edges(add_geo(resolve_myself(delete_unused_nodes(json.load(sys.stdin)))))) - print (json.dumps(nodes)) + try: + with open(GEODB) as f: f.read() + except: + print("cannot open {} (GEODB in env)".format(GEODB)) + sys.exit(1) + try: + nodes = add_jitter(add_coords_to_edges(add_geo(resolve_myself(delete_unused_nodes(json.load(sys.stdin)))))) + print (json.dumps(nodes)) + except Exception as e: + print("cannot parse data received via stdin") + print(e) + +if __name__ == "__main__": + main() diff --git a/retiolum/scripts/adv_graphgen/tinc_stats/Graph.py b/retiolum/scripts/adv_graphgen/tinc_graphs/Graph.py index 2fb09a58..b001780d 100755 --- a/retiolum/scripts/adv_graphgen/tinc_stats/Graph.py +++ b/retiolum/scripts/adv_graphgen/tinc_graphs/Graph.py @@ -1,12 +1,12 @@ #!/usr/bin/python -from BackwardsReader import BackwardsReader +from .BackwardsReader import BackwardsReader import sys,json,os -from Supernodes import check_all_the_super -from Services import add_services -from Availability import get_node_availability +from .Supernodes import check_all_the_super +from .Services import add_services +from .Availability import get_node_availability import sys,json from time import time -DUMP_FILE = "/krebs/db/availability" +DUMP_FILE = os.environment.get("AVAILABILITY_FILE", "tinc-availability.json") def resolve_myself(nodes): @@ -19,6 +19,7 @@ def resolve_myself(nodes): v["external-ip"] = to["addr"] return nodes + def dump_graph(nodes): from time import time graph = {} @@ -209,7 +210,7 @@ def anonymize_nodes(nodes): i = str(int(i)+1) return newnodes -if __name__ == "__main__": +def main(): supernodes= [] if len(sys.argv) != 2 or sys.argv[1] not in ["anonymous","complete"]: print("usage: %s (anonymous|complete)") @@ -247,4 +248,8 @@ if __name__ == "__main__": print_stat_node(nodes) print ('}') + +if __name__ == "__main__": + main() + # vim: set sw=2:ts=2 diff --git a/retiolum/scripts/adv_graphgen/tinc_stats/Log2JSON.py b/retiolum/scripts/adv_graphgen/tinc_graphs/Log2JSON.py index a81e2bef..7df042fd 100755 --- a/retiolum/scripts/adv_graphgen/tinc_stats/Log2JSON.py +++ b/retiolum/scripts/adv_graphgen/tinc_graphs/Log2JSON.py @@ -28,10 +28,9 @@ This tool dumps all tinc node informations as json ENVIRONMENT VARIABLES: TINC_NETWORK The tinc network to dump (default: retiolum) - LOG_FILE If legacy tinc is used, defines the log file where tinc stats are dumped in - (default: /var/log/everything.log) """ % argv[0]) exit(1) + def debug(func): from functools import wraps @wraps(func) @@ -52,42 +51,18 @@ def parse_tinc_stats(): elif which("tincctl"): return parse_new_input("tincctl") #old tinc + elif which("tincd"): + print("old tincd not supported") + sys.exit(1) else: raise Exception("no tinc executable found!") - -#@debug -def get_tinc_block(log_file): - """ returns an iterateable block from the given log file (syslog) - This function became obsolete with the introduction of tincctl - """ - from BackwardsReader import BackwardsReader - tinc_block = [] - in_block = False - bf = BackwardsReader(log_file) - BOL = re.compile(".*tinc.%s\[[0-9]+\]: " % TINC_NETWORK) - while True: - line = bf.readline() - if not line: - raise Exception("end of file at log file? This should not happen!") - line = BOL.sub('',line).strip() - - if END_SUBNET in line: - in_block = True - - if not in_block: - continue - tinc_block.append(line) - if BEGIN_NODES in line: - break - return reversed(tinc_block) def parse_new_input(tinc_bin): nodes = {} pnodes = subprocess.Popen( [tinc_bin,"-n",TINC_NETWORK,"dump","reachable","nodes"], stdout=subprocess.PIPE).communicate()[0].decode() - #pnodes = subprocess.check_output(["tincctl","-n",TINC_NETWORK,"dump","reachable","nodes"]) for line in pnodes.split('\n'): if not line: continue l = line.split() @@ -117,9 +92,12 @@ def parse_new_input(tinc_bin): pass #node does not exist return nodes -if __name__ == '__main__': +def main(): from sys import argv if len(argv) > 1: usage() else: print (json.dumps(parse_tinc_stats())) + +if __name__ == '__main__': + main() diff --git a/retiolum/scripts/adv_graphgen/tinc_stats/Services.py b/retiolum/scripts/adv_graphgen/tinc_graphs/Services.py index 6752e116..227e5aba 100644 --- a/retiolum/scripts/adv_graphgen/tinc_stats/Services.py +++ b/retiolum/scripts/adv_graphgen/tinc_graphs/Services.py @@ -1,4 +1,5 @@ -services_dir="/home/makefu/r/services" +import os,sys +services_dir=os.environment.get("SERIVCES_DIR","/home/reaktor/nag.services") def add_services(nodes): for k,v in nodes.items(): n = nodes[k] @@ -10,8 +11,15 @@ def add_services(nodes): except Exception as e: n["services"] = ["Error: No Service File!"] return nodes -if __name__ == "__main__": +def main(): import json,sys - nodes = add_services(json.load(sys.stdin)) - print (json.dumps(nodes,indent=4)) + try: + nodes = add_services(json.load(sys.stdin)) + print (json.dumps(nodes,indent=4)) + except: + print("unable to parse json data from stdin") + sys.exit(1) + +if __name__ == "__main__": + main() # vim: set expandtab:ts=4:sw=4 diff --git a/retiolum/scripts/adv_graphgen/tinc_stats/Supernodes.py b/retiolum/scripts/adv_graphgen/tinc_graphs/Supernodes.py index 7e1f4dae..c8514c66 100755 --- a/retiolum/scripts/adv_graphgen/tinc_stats/Supernodes.py +++ b/retiolum/scripts/adv_graphgen/tinc_graphs/Supernodes.py @@ -23,6 +23,7 @@ def find_potential_super(path="/etc/tinc/retiolum/hosts"): if addrs : yield (f ,[(addr ,int(port)) for addr in addrs]) + def try_connect(addr): try: from socket import socket,AF_INET,SOCK_STREAM @@ -34,7 +35,7 @@ def try_connect(addr): return addr except Exception as e: pass - #return () + def check_one_super(ha): host,addrs = ha @@ -44,16 +45,21 @@ def check_one_super(ha): if ret: valid_addrs.append(ret) if valid_addrs: return (host,valid_addrs) -def check_all_the_super(path="/etc/tinc/retiolum/hosts"): + +def check_all_the_super(path): from multiprocessing import Pool p = Pool(20) return filter(None,p.map(check_one_super,find_potential_super(path))) +def main(): + import os + hostpath=os.environment.get("TINC_HOSTPATH", "/etc/tinc/retiolum/hosts") -if __name__ == "__main__": - """ - usage - """ - for host,addrs in check_all_the_super(): + for host,addrs in check_all_the_super(hostpath): print("%s %s" %(host,str(addrs))) + +if __name__ == "__main__": + main() + +# vim: set expandtab:ts=:sw=2 diff --git a/retiolum/scripts/adv_graphgen/tinc_graphs/__init__.py b/retiolum/scripts/adv_graphgen/tinc_graphs/__init__.py new file mode 100644 index 00000000..414ffe99 --- /dev/null +++ b/retiolum/scripts/adv_graphgen/tinc_graphs/__init__.py @@ -0,0 +1 @@ +__version__="0.2.3" diff --git a/retiolum/scripts/adv_graphgen/map.html b/retiolum/scripts/adv_graphgen/tinc_graphs/static/map.html index ef8a0565..ef8a0565 100644 --- a/retiolum/scripts/adv_graphgen/map.html +++ b/retiolum/scripts/adv_graphgen/tinc_graphs/static/map.html diff --git a/retiolum/scripts/adv_graphgen/tinc_stats/__init__.py b/retiolum/scripts/adv_graphgen/tinc_stats/__init__.py deleted file mode 100644 index f0fc8520..00000000 --- a/retiolum/scripts/adv_graphgen/tinc_stats/__init__.py +++ /dev/null @@ -1,7 +0,0 @@ -import Availability -import BackwardsReader -import Log2JSON -import Supernodes -import Geo -import Graph -import Services |