sensor profiler complete
[oweals/gnunet.git] / src / sensor / profiler.py
1 import argparse
2 import math
3 import networkx
4 import random
5 import tempfile
6 import os
7 import time
8 import matplotlib.pyplot as plt
9 from subprocess import Popen, PIPE, STDOUT
10
11 node_colors = None
12 graph = None
13 pos = None
14
15 def get_args():
16   parser = argparse.ArgumentParser(description="Sensor profiler")
17   parser.add_argument('-p', '--peers', action='store', type=int, required=True,
18                       help='Number of peers to run')
19   return parser.parse_args()
20
21 def generate_topology(peers, links):
22   global graph
23   global node_colors
24   global pos
25   graph = networkx.empty_graph(peers)
26   for i in range(0, links):
27     a = 0
28     b = 0
29     while a == b:
30       a = random.randint(0, peers - 1)
31       b = random.randint(0, peers - 1)
32     graph.add_edge(a, b)
33   node_colors = [0] * peers
34   pos = networkx.layout.spring_layout(graph)
35
36 def create_topology_file():
37   global graph
38   nodes = list()
39   for i in range(len(graph.edge)):
40     nodes.append(list())
41   for e in graph.edges():
42     nodes[e[0]].append(e[1])
43   print nodes
44   f = tempfile.NamedTemporaryFile(delete=False)
45   for i in range(len(nodes)):
46     if len(nodes[i]) == 0:
47       continue
48     f.write('%d:' % i)
49     f.write('|'.join(map(str, nodes[i])))
50     f.write('\n')
51   # f.close()
52   return f.name
53
54 def draw_graph():
55   global graph
56   global node_colors
57   global pos
58   t = int(time.time())
59   inc = 2
60   name = str(t) + '.png'
61   while os.path.exists(name):
62     name = '%d(%d).png' % (t, inc)
63     inc += 1
64   print 'Drawing graph to file: %s' % name
65   plt.clf()
66   networkx.draw(graph, pos=pos, node_color=node_colors, with_labels=range(len(graph.node)), cmap=plt.cm.Reds, vmin=0, vmax=2)
67   plt.savefig(name)
68
69 def peers_disconnected(p1, p2):
70   global graph
71   print 'Disconnected peers %d and %d' % (p1, p2)
72   if p2 not in graph[p1]:
73     print 'Link does not exist'
74     return
75   graph.remove_edge(p1, p2)
76   draw_graph()
77
78 def anomaly_report(report):
79   global node_colors
80   if 0 == report['anomalous']:
81     node_colors[report['peer']] = 0
82   else:
83     node_colors[report['peer']] = 1 + report['neighbors']
84   draw_graph()
85
86 def handle_profiler_line(line):
87   if not line:
88     return
89   print line
90   if 'Peer disconnection request sent' in line: # Peers disconnected
91     parts = line.split(':')
92     peers = parts[-1].split(',')
93     peers_disconnected(int(peers[0]), int(peers[1]))
94     return
95   if 'Anomaly report:' in line:
96     parts = line.split('Anomaly report:')
97     anomaly_report(eval(parts[1]))
98     return
99
100 def run_profiler(peers, topology_file):
101   cmd = "GNUNET_FORCE_LOG='gnunet-sensor-profiler;;;;DEBUG' gnunet-sensor-profiler -p %d -t %s > log 2>&1" % (peers, topology_file)
102   process = Popen([cmd], shell=True)
103   time.sleep(0.5)
104   line = ''
105   f = open('log')
106   while process.poll() is None:
107     for c in f.read():
108       if not c or c == '\n':
109         handle_profiler_line(line)
110         line = ''
111       else:
112         line += c
113   os.remove('log')
114
115 def main():
116   args = vars(get_args())
117   num_peers = args['peers']
118   if num_peers < 3:
119     print 'Min number of peers is 3'
120     return
121   num_links = int(math.log(num_peers) * math.log(num_peers) * num_peers / 2)
122   # Generate random topology
123   generate_topology(num_peers, num_links)
124   print 'Generated random topology with %d peers and %d links' % (num_peers, num_links)
125   # Create TESTBED topology file
126   top_file = create_topology_file()
127   print 'Created TESTBED topology file %s' % top_file
128   draw_graph()
129   # Run c profiler
130   run_profiler(num_peers, top_file)
131   
132 if __name__ == "__main__":
133   main()